Our Blog

Deploying app ENV variables with Rbenv, Passenger and Capistrano

New: Intercity now makes it really easy to configure Environment Variables for your Rails app. Take a look this announcement: New in Intercity: Environment Variables per Rails app.

Rails 4.1 now has a secrets.yml file where you can store secrets, API keys, passwords, etc. to be used for your application. The secrets.yml is also the default file to specify the SECRET_KEY_BASE for your app. In development and test, these keys are already pre-filled by Rails. For production, you’ll see this in the file:

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

As the comment says, you should not just replace this with a secret key and keep it in your repository. You should load it from the environment. You can do this very easily with Rbenv, the Rbenv Vars plugin and Capistrano. Here’s how we do it in Intercity:

1. Make Pusion Passenger use Rbenv

First, the passenger_root setting in our Phusion Passenger configuration points to our Rbenv ruby. Here it is in our /etc/nginx/conf.d/passenger.conf. If you manage your server with Intercity, this is already configured.

passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
passenger_ruby /opt/rbenv/shims/ruby;
passenger_show_version_in_header off;
passenger_resist_deployment_errors on; # Only in Phusion Passenger Enterprise
passenger_rolling_restarts on; # Only in Phusion Passenger Enterprise
passenger_max_pool_size 10;

This will make Passenger use the correct Ruby version for each app. The Ruby version is determined by setting it in the .ruby-version in your Rails app.

2. Installing the rbenv-vars plugin

The rbenv-vars plugin is the important part. This plugin loads up all the environment variables from a .rbenv-vars file into our app’s ENV hash. If you manage your server with Intercity the plugin is installed by default.

If you don’t have Rbenv yet you can install it by going into the plugins directory of your rbenv installation and cloning the plugin from GitHub, like so:

$ cd /opt/rbenv/plugins
$ git clone https://github.com/sstephenson/rbenv-vars.git

That’s all there is to it to using the plugin.

3. Setting SECRETKEYBASE for your Rails application

In the shared folder of your deployment directory for your application, create a file called .rbenv-vars. We’re going to generate a new secret key and put SECRET_KEY_BASE variable into that file.

Generate a new secret in your Rails app on your development machine:

$ rake secret
11a2bc43c4de634da44f1c0c2347820e0b96155947fe8229d555a4c5e7dfeaaaaed640a0fd34bff2e1ad3d02ebf9ab9bf68756c4dd7c166450d92ae73f3ab277

Then on your server. Put the secret into your shared/.rbenv-vars file. The file should look like this:

SECRET_KEY_BASE=11a2bc43c4de634da44f1c0c2347820e0b96155947fe8229d555a4c5e7dfeaaaaed640a0fd34bff2e1ad3d02ebf9ab9bf68756c4dd7c166450d92ae73f3ab277

4. Deploy with Capistrano

The last thing to set up, is tell Capistrano that it needs to symlink the shared/.rbenv-vars file into each of your deployments. So edit config/deploy.rb in your Rails app and modify the line with the linked_files setting:

set :linked_files, %w{config/database.yml .rbenv-vars}

Now deploy your application with Capistrano and your secrets.yml will use ENV['SECRET_KEY_BASE'] that you specified in shared/.rbenv-vars.

You can now add more configuration keys or API keys to .rbenv-vars to use them in your app via ENV!

Michiel Sikkes

Follow us on Twitter

Subscribe via email

Automatically get new articles with product updates and Rails hosting best practices.

Join the Discussion