A buildpack based on the idea of packages, delivering a modular system and basic dependency management.
It is possible to use this buildpack as is, and contain all your extra data in your project itself.
Configuration for this buildpack should always be placed inside your project under
A minimum configuration has at least these files living in
install: contains a list of packages to install separated by a space or a package per line.
package: the name of the buildpack as reported to heroku.
release: a release file as specified by heroku.
Optional components are:
installers: a directory containing custom installers.
compile: a custom compile script for your project that will be run after all the packages have been installed.
repos: a file containing package repositories, the presence of this file enables the package manager.
Packages are represented by installer scripts that install one specific part of your environment, for example there is an installer included under
installers which install a basic nginx webserver.
The name of a package is the name of it's installer script without the
This buildpack includes a package manager which allows you to centralize the management of your packages.
Enabling the package manager
By default the package manager is disabled, you can enable it simply by adding a
repos file to your
The file-format of the
repos file is as simple as a link ( any link supported by curl ) per line of the file.
A repository is a plain text file using the following format
<package-name> <package-link> <package-md5> <comments> where each package is on its own line. It is important to use a space to separate the package from its link, a tab is currently not supported.
<package-link> is a link ( any link supported by curl ) to the installer file for the package.
<package-md5> is a md5 hash of the installer file which is used to check for an outdated cache.
A sample repository
nginx-deploy-page http://jorgen.evens.eu/heroku/nginx-deploy-page.sh 9bbb050c6bba8c7ad8f738ef056088ae # Exposes deployment information through a static page.
Note: Currently no versioning of packages is available. If you would like to add multiple versions you will have to include the version in the package name.
nginx-1.4.2 for example.
Repository sample + tools
There is a github repository with the scripts to generate a repository for the packages contained within it.
You can build your own buildpack by forking this repository and adding your own installers, but if you would
like to keep your buildpack as clean as possible you can also install installer scripts in the
/build/heroku/installers folder of your project.
An alternative is to use the package manager to distribute the packages.
The buildpack passes 4 variables into the installer, three of which are the exact same variables as Heroku passes to the compile script. The fourth indicates the location at which the installer was stored.
These directories are created for you when the buildpack runs.
Environment variables you may have set in Heroku will be loaded and available to your installer script as well.
Note: When using the package manager
$INSTALLER_DIR will point to the location in the repository file rather than to the local copy that gets downloaded.
An installer has access to some helper functions to print to the console and to manage dependencies it might require.
print_action <message>: prints the message prefixed with the '-------> ' arrow.
print <message>: prints the message prefixed with spaces to align it with
dependency_require <package>: requires the installation of the dependency before continuing.
dependency_mark <package>: marks a package as installed. This is primarily for internal use.
download <url> <target> [<md5>]: Downloads a file to the specified location and checks if the MD5 hash is correct.
cached_download <url> <target> [<md5> [<exit_on_fail>]]: Performs the same function as
downloadbut caches the files.
unpack <url> <md5> [<target> [<clean_target>]]: Downloads the specified .tar.gz file using
cached_downloadand extracts the contents into
env_extend <environment_variable> <value_to_be_added>: Append
environment_variableseparated by a semicolon. Use this to extend
Note: You should NOT mark your own package as installed using
dependency_mark, this is done for you.
dependency_mark use case
A sample use-case for the
dependency_mark function is given here to illustrate its use.
If your package can be used as a drop-in replacement for another package you can mark the original package as installed so your package does not get overwritten when a different package depends on the original.
- There is a generic
nginxpackage in your repository
- There is a
nginx-modulepackage which is nginx with a specific module compiled in.
- There is a package
nginx-statuswhich depends on the generic
In this scenario we would like to combine
nginx-status, if we would setup our
install file like illustrated below we would overwrite
nginx-module with generic
nginx-status depends on it.
To solve this problem we can mark
nginx as installed at the end of our
nginx-module installer by calling
nginx-status is installed
nginx will be reported as installed and
nginx-module will not get overwritten.
boot.sh file is always created with a shebang
#!/bin/sh followed by an empty line. If your installer wants to add something to the
boot.sh file you should simple append the lines to the
It is important that you send blocking applications to the background using
&. For example:
wait will be added to the end of the boot.sh script so that the script will wait for the background tasks to complete and heroku will not think that the script exited. This way all the commands in the
boot.sh file get executed and all services start as they are supposed to.
Project specific compile
The project specific
compile script has access to the same functionality as a custom installer and is for all intents and purposes a custom installer that always gets run at the end.
Setting the environment variable
CLEAN_CACHE to a non empty value will result in the buildpack removing the
CACHE_DIR before running any installers.
This will ensure that the cache is empty and all the required packages and files will be downloaded again.
I really appreciate any contribution you would like to make, so don't hesitate to report an issue or submit pull requests.
Special thanks to these people for contributing to this project
This project is available under the New BSD License.