Cloud Foundry can be wonderfully simple to use for 99% of web applications. It is now even more wonderful and more simple by allowing us to install Debian packages. Cloud Foundry containers do not grant root access, so installing Debian packages has not been possible. But it now is with the apt buildpack.

With or without extra Debian packages, deploying Cloud Foundry applications is always simple:

cf push  

So easy. So delightful.

1% of the time, my application has some niche dependency. A package that isn't pre-installed on the base image of a Cloud Foundry container or a dependency that the buildpack doesn't natively support.

For example, I wanted to build a mini admin UI for some BOSH environments. The BOSH director does have an API, but there is only a formal client library in Golang. Fortunately, the bosh CLI is fast and most commands have JSON output.

I realized I could get a long way by writing my UI in Ruby on Rails and invoke the bosh CLI to interact with a BOSH director.

Even better, the bosh CLI uses environment variables for targeting and authentication -- which matches perfectly with how Cloud Foundry likes to configure its running applications.

Here's an example of a Ruby application that uses a Debian packaged version of the bosh CLI, and hidden environment variables for configuration, to interact with a BOSH environment.:

bosh-demo

Conveniently, I had packaged the bosh CLI as a Debian package recently. All I needed was a way to install my bespoke Debian package from my bespoke https://apt.starkandwayne.com/ Debian repository as part of cf push.

Fortunately, Cloud Foundry now has an apt buildpack to make this very easy to combine.

Any Cloud Foundry application can now have any Debian package installed during the cf push staging sequence. The installed packages (and their nested dependencies) will be baked into the droplet and will be consistent across every instance of the application.

Step 1. The apt.yml file.

For my demo app I needed the bosh-cli package from https://apt.starkandwayne.com to be installed during cf push.

All I need to create is an apt.yml file:

---
keys:  
- https://raw.githubusercontent.com/starkandwayne/homebrew-cf/master/public.key
repos:  
- deb http://apt.starkandwayne.com stable main
packages:  
- bosh-cli

This apt.yml file corresponds to the https://apt.starkandwayne.com instructions:

wget -q -O - https://raw.githubusercontent.com/starkandwayne/homebrew-cf/master/public.key | apt-key add -  
echo "deb http://apt.starkandwayne.com stable main" | tee /etc/apt/sources.list.d/starkandwayne.list  
apt-get update

apt-get install bosh-cli  

The primary difference, aside from syntax, is that Cloud Foundry applications do not have root access, so I cannot simply apt-get install packages. The apt-buildpack installs packages into a location

Step 2. Using multiple buildpacks

The apt buildpack is not the only buildpack we need. My app is a Ruby app. It needs the standard ruby buildpack too.

All modern Cloud Foundry distributions will have two ways to use multiple buildpacks: a cf push method and cf v3-push method.

I've written up both sets of instructions in the demo application README.

In brief, cf push only allows a single buildpack - so you use https://github.com/cloudfoundry/multi-buildpack/. You then create a multi-buildpack.yml file to specify the ordered set of buildpacks.

buildpacks:  
- https://github.com/cloudfoundry/apt-buildpack
- https://github.com/cloudfoundry/ruby-buildpack

NOTE: The last buildpack must be the runtime buildpack.

Alternately, cf v3-push natively supports multiple buildpacks. You provide the ordered list as flags:

cf v3-push bosh-cli-web-demo \  
  -b https://github.com/cloudfoundry/apt-buildpack \
  -b ruby_buildpack

Again, the final buildpack must be buildpack that will initialize and run the web application.

Learn more

Watch Keaty Gross at Cloud Foundry Summit Basel 2017 to learn more about multi-buildpack, apt-buildpack, and the future of Cloud Foundry!