We all want our applications to be simple to configure. One way to do that is to use environment variables and that is also the conventions defined in “The Twelve-Factor App“. If you are not familiar with the thinking behind “The Twelve-Factor App” it is all about making applications that are simple to deploy and scale, as well as minimizing the difference between the development and production environment. I warmly recommend that you take a closer look there after you finished reading this post.
Separating configuration from code in this manner puts you in good company with the likes of Heroku and one of my major inspirations Avdi Grimm.
One good example of something that will differ between the different environments (development, staging and production) is the database url and login information. This is also information that you do not want to share with the public if you share the source code of your application publicly on Github or Bitbucket.
Why Environment Variables?
Storing login information, connection information and API-keys in environment variables is a simple and easy way to make your applications easy to configure between environments and it can also help you to keep that information safe.
For example, there have recently been instances where people’s Amazon S3 information have been deployed and displayed publicly on Github. Bot nets scrape the web for this kind of information, then use your account to mine for bitcoins. As a byproduct you get a large credit card bill.
Using environment variables can be tricky, though, especially since you will most likely have different configurations for different application and thus setting the environment variables directly in zsh or bash is not a very good idea.
This problem is solved by the fantastic Ruby gem “Dotenv”.
How?
There a few minor differences between using “Dotenv” in a pure Ruby program or if you use Rails.
If you use Rails
Add the following line to your Gemfile (which you have since Rails use Bundler) gem 'dotenv-rails', :groups => [:development, :test]
and then run “bundle install”.
After that you create the .env file in the application root.
Rails will autoload the file during a callback known as before_configuration. That callback is fired as soon as the Application class in “config/application.rb” is defined.
If you use plain Ruby, Sinatra etc.
Start with installing the gem. Preferably using Bundle or just install by using the “gem” command:
gem install dotenv
After that you create the file “.env” (just as the gem is called” in your application root and then we just need to get the file loaded on application start.
To load the file you just do the following as early as possible in your application.
require 'dotenv'
Dotenv.load
If you need to use dotenv in rake you need to make sure that the task depends on dotenv. To do that you require ‘dotenv/tasks’ and then define every task so that they depend on the dotenv symbol.
require 'dotenv/tasks'
task :dependent_task => :dotenv do
# do the work that needs .env to work
end
File syntax
To define environment variables in your file you define them with a name and an assigned value:
DATABASE_URL=postgres://user@localhost:5432/database
ADMIN_PASSWORD=super_secret_password
If you want to use multiple files for your configuration then check out this great post by Avdi Grimm.