Config Vars for Deploy-Specific Settings

Say you’re working on a Rails app, and you want to publish your code on Github. Most apps have some deploy-specific private config values – for example, if you’re using the S3 storage backend for Paperclip, and your S3 keys are saved in config/amazon_keys.yml. You certainly don’t want to push those up to Github – what to do?

You could maintain a separate deploy branch, and commit your deploy config only to that. You can then work on the main branch, and rebase the deploy branch whenever you go for a deploy. That’s a bit of extra work you could do without, though – and you know sooner or later, you’re going to accidentally push the wrong branch to Github, putting your S3 keys up for the whole world to see. Oops.

Wouldn’t it be nice avoid all this headache by storing the data specific to your app’s deploy in a separate configuration registry?

Now you can. Check it out:

$ heroku config:add S3_BUCKET=mybucket S3_KEY=8N029N81 S3_SECRET=9s83109d3+583493190
Adding config vars:
  S3_BUCKET => mybucket
  S3_KEY    => 8N029N81
  S3_SECRET => 9s83109d3+583493190
Restarting app...done.

Your config vars are now accessible in the environment variables for your deployed app. Configure Paperclip like this:

has_attached_file :photo,
  :storage => :s3,
  :s3_credentials => {
    :access_key_id => ENV['S3_KEY'],
    :secret_access_key => ENV['S3_SECRET']
  },
  :bucket => ENV['S3_BUCKET'],
  :path => ":attachment/:id"

Set up like this, your public code and your deployed code can be exactly the same. Push to Github all day long with no fear of leaking your private credentials. Clean and neat, no fuss, no muss.

This also means you can set different config vars for different deployed versions of the app. For example, if you run a staging deploy of your code on Heroku, you can set it to use a different S3 bucket – maybe “myapp_assets” for production and “myapp_staging_assets” for staging.

What about running locally, deploying to a traditional host? Since these are just environment variables, you can set them just as you normally would – in your .bashrc (export S3_BUCKET=mybucket), or on the command line when you run the server.

Or, you can check for the presence of the vars, and use defaults when they don’t exist. In the case of Paperclip, you might do:

has_attached_file :photo,
  :storage => ENV['S3_BUCKET'] ? :s3 : :filesystem,
  ...

Now when you run locally, it’ll use the filesystem store; but running on a deployed app with the S3_BUCKET var set, it’ll automatically go to the right place.

There are many other uses for config vars. For example, you can set RACK_ENV to something other than the default of ‘production’. (RAILS_ENV and MERB_ENV will automatically mirror RACK_ENV on Heroku.) So if you prefer the traditional approach of storing different keys for different environments (development/staging/production) in various config/something.yml files, set your RACK_ENV as appropriate for your staging and production deployed apps on Heroku.

Read the full documentation. Note that you’ll need to grab the 0.7 Heroku client gem (it’s in Rubyforge now, so `gem install heroku` will do the trick) to use this feature.

Tags: newfeatures

Browse the blog archives or subscribe to the full-text feed.