Developing Apps with Environment Variables

This post is mostly a reminder to myself about my setup to deal with environment variables when working on web applications. I develop in Ruby on OS X, to give you the gist of my setup.

It wasn’t until I switched from ASP.NET and C# to Ruby that I started using Heroku. Heroku is awesome, but has its opinions of how apps should be setup. It was a little bit of a mental shift coming from Microsoft technologies, but I love it now.

Importing & Exporting Config Variables – The Heroku CLI

Heroku wants you to store all credentials and other settings in environment variables. This allows you to modify credentials and such without affecting the code. It also makes sure that the code doesn’t have sensitive information in it when checked into git.

Heroku’s command line utility lets you easily list and update environment variables on Heroku. However, it’s not very easy to get those environment variables loaded when developing on your local machine. There’s a plugin for Heroku’s command line utility that lets you export environment variables to a “.env” file. I’ve created a modified version of the plugin that lets you specify separate files for each environment (e.g. development.env, staging.env, production.env). These files can be modified and pushed back to Heroku easily.

Loading Environment Variables – Using Foreman

Now that we can manage the environment variables on Heroku, how do we use them locally? Well, that’s what Foreman is for. It was created by David Dollar, along with the original Heroku CLI plugin that I tweaked. The beautiful thing is that Foreman uses the same “.env” files and lets you specify the filename to load.

A quick step back: Foreman lets you easily start up multiple processes required to run your web app. You can specify what processes to start in a Procfile, which is the basis for Heroku web apps.

Now, you can just run a command such as “foreman start” and it will load up the Procfile in the current directory. You can also specify your environment variables to load such as “foreman start -e development.env”. Your Procfile might simply have “web: rails s” in it, so Foreman just runs that command with environment variables automatically loaded from your file.

The latest piece of the puzzle I put together was to get the environment variables loaded when I wanted to use the Rails console. Foreman has a nice little hidden command which is “foreman run”. The latest version as of a day or two ago lets you use your “.env” file. All you have to do is run “foreman run -e development.env rails c” and you’re good to go!

Simplifying Your Development Environment – Use Shortcuts!

Last but not least, I created some shell functions that really easily let me run any command with my environment variables loaded. Additionally, I wrap my command in “bundle exec” where appropriate to make sure the proper gems are loaded when running my command. Here they are:

function dev() { if [[ -f Gemfile && $@ != bundle* ]]; then foreman run -e development.env bundle exec $@ ; else foreman run -e development.env $@; fi; }
function prod() { if [[ -f Gemfile && $@ != bundle* ]]; then foreman run -e production.env bundle exec $@ ; else foreman run -e production.env $@; fi; }
function stage() { if [[ -f Gemfile && $@ != bundle* ]]; then foreman run -e staging.env bundle exec $@ ; else foreman run -e staging.env $@; fi; }

All you have to do now is prefix any command with “dev”, “prod”, or “stage” to run the command with those environment variables. For example, I’m constantly running “dev rails c” and everything works flawlessly!

Update: Using Environment Variables in Your Gemfile on Heroku

I am hosting some private gems via git and to access them Rails needs a username and password. By now, you know where the credentials are stored. However, Heroku does not load environment variables when building the slug. To enable this, you need to install a Heroku “labs” plugin by running this command:

heroku labs:enable user_env_compile -a myapp

Hopefully all my bases are now covered…..

Share

1 comment

  1. Hi,

    Thanks for this, I wasn’t using Foreman, but your tutorial made it pretty clear.

    I just reviewed your dev shell function so that I can use “dev start” to run “foreman start -e development.env” while still being able to run any command with “dev command”. Here is the snippet:

    function dev() { if [[ $1 == start ]]; then foreman start -e development.env; else if [[ -f Gemfile && $@ != bundle* ]]; then foreman run -e development.env bundle exec $@ ; else foreman run -e development.env $@; fi; fi; }

    Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *


one + = 5

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Additional comments powered by BackType