This article was published on April 19th 2015 and takes about 4 minutes to read.
Use it with caution — it is probably still valid, but it has not been updated for over a year.
Setting environment variables for your Rails applications can be tricky at times. Learn about 3 gotchas and my preferred way to define them in a production environment.
Some time ago, Rails introduced the file
config/secrets.yml to store your application's secret variables. When you create a new Rails application, this file defines a variable called
secret_key_base which your application uses to sign cookies.
When you take a look at this file, you will notice that each environment (development, test and production) has its own
secret_key_base. What's important is that while for development and test environment the variable's value is set directly in this file, Rails expects to read this value from an environment variable when running in production.
Setting values from environment variables is an elegant way to prevent sensible data (like API tokens or passwords) from being stored in your application's code repository.
But there are gotchas you have to be aware of:
A default Rails application needs at least
RAILS_ENV set in order to start.
RAILS_ENV nearly always falls back to a default value (making your app start in development mode in the worst case), an undefined
SECRET_KEY_BASE simply results in your application serving a blank page. On further investigation, you will find messages complaining about missing
secret_key_base in your application server's log file.
The preferred way to set environment variables on CentOS systems is to define them in a file under
/etc/profile.d. Scripts in this directory are run for each new login shell so you can use the
export command to define environment variables:
export RAILS_ENV=production export SECRET_KEY_BASE=abc export API_TOKEN=def
When you start your application server using an init script, you may experience this behaviour:
Having defined your application's environment variables in a file under
/etc/profile.d, your application starts without problems when you manually run its init script but fails to do so when your server reboots.
The problem here is that these files are only executed for login shells. When your init script runs in the course of the boot process, these files are not executed and therefore no environment variables are set.
You can remedy that by sourcing the according file inside your init script with
If you have configured everything correctly and still get strange messages about a missing
SECRET_KEY_BASE in your application server's log, the you may suffer from a really mean problem:
I had problems with my internet connection a few weeks ago resulting in massive package loss (sometimes up to 50%). While installing/updating my application's gems,
bundle install sometimes had to be run several times because Bundler could not resolve the IP address of rubygems.org every now and then and thus halted the installation process.
Even though at some point all gems were installed, some of them obviously were corrupted resulting in my application not being able to read the
secrets.yml file properly (and thus setting the
Re-installing all my application's gem dependencies solved this issue.
I am using rbenv on my production machines to manage Ruby versions and I recently discovered rbenv-vars, which is since my preferred way to manage my applications' enviroment variables.
rbenv-vars is an rbenv plugin. To install it, simply clone
firstname.lastname@example.org:sstephenson/rbenv-vars.git to your rbenv installation's
Once installed, it will look for a file called
.rbenv-vars in your current working directory or any of its parent directories. To set environment variables, just define them as key/value pairs:
RAILS_ENV=production SECRET_KEY_BASE=abc API_KEY=def
These variables will be set whenever a new Ruby process is spawned. To set global default values, define them in
development(maybe for debugging purposes) without affecting the others — this would be quite hard to accomplish with global environment variables defined in files under
However, one small gotcha remains:
Since these environment variables are set when a new Ruby process spawns, you will not be able to see them using *nix commands like
echo $RAILS_ENV. If you want to know which variables are set, use the command
When using RVM, take a look at the
.ruby-env file, which seems to offer the same functionality.