It may seem like common sense to some but using environment variables to mask sensitive access/account information is something more and more junior developers are NOT learning in code schools. Join me as I take a look at some easy ways to prevent that important information from being pushed to your public code base.
This post assumes you’re using Git as your version tracking system. I’ll be updating this with Mercurial commands in the next week or so. Thank you for your patience!
In this age of identity theft and corporate data breaches we are constantly bombarded by reminders to set strong passwords, use two factor authentication, and keep our personal information out of the hands of strangers as much as possible. Keep your Social Security card locked in a safe deposit box or safe, cut up old credit cards, and things of that nature are almost held as universal constants these days. Danger is lurking everywhere…
Yet when it comes to public code repositories some developers unknowingly present sensitive information openly to the world.
While there are numerous ways sensitive information can be exposed via public repositories, I’m going to focus on using environment variables to “hide” things like credentials, keys, and access tokens from the outside world so you can safely push your code to GitHub.
I will cover several different ways to implement environment variables in a Ruby on Rails application so that you at least know some of the options available to you.
Note: Methods 1 through 3 will require some manual work to upload the untracked environment variable file to your production system. This is less than ideal but is currently necessary for safety and security of the information.
1. A Custom Local Environment File
The method I have most commonly used when creating side projects with sensitive access credentials is to create a local environment file. Rails 4.1 provides its own
secrets.yml file that I’ll cover later, but I do it this way just to get in the practice of knowing HOW things work instead of just relying on “magic” and sugar.
The Process: (after you’ve cloned or initialized the git repo)
- Create a
local_env.ymlfile in your
/config/ directoryof your app.
Inside that file you’d layout your environment variables for your particular use case like the following example:
Add the file to
.gitignoreby opening the
.gitignorefile in the root of your app directory and placing a relative path to your
local_env.ymlfile like this:
config/application.rbfile and add the following lines inside the
class Application < Rails::Applicationsection:
env_file = File.join(Rails.root, 'config', 'local_env.yml')
YAML.load(File.open(env_file)).each do |key, value|
ENV[key.to_s] = value
This will open the config/local_env.yml file and then set the environment variables based on the key/value pairs in the file. Keep in mind that this code requires that the file exists.
In order to use the environment variables in your code you simply need to use this format:
So in the case of our earlier example, you would use:
*Code sample modified from the snippet provided on the RailsApps Project’s Rails Environment Variables article by Taylor Mock and Daniel Kehoe
Starting in Rails 4.1 the
secrets.yml file has been made available to hold environment variables. You still need to manually add this file to the
.gitignore file, Rails does not currently do this for you. Otherwise this functions much the same as method 1 except for three differences.
The first difference is that Rails will create and populate this file by default with the
secret_key_base for your application. It will also load this file by default without you needing to update the
Next, you don’t need to use the same
KEY_NAME = VALUE_NAME format as with the custom
.yml file. You can enter in your key/value pairs in lowercase as they’ll be accessed in a different manner than method 1
The final difference is that you can use
Rails.application.secrets.<key_name> to access the environment variables in your application. Keeping with our example from method 1, this would be used as follows:
3. dotenv (a Ruby gem)
The dotenv gem simplifies some of the setup of things by allowing you to create a .env file at the root of your application directory to hold the sensitive information. Like methods 1 and 2, you still need to add the
.env to your
- Include the gem in your
group :development, :test do
gem 'dotenv-rails', '~> version_number'
- In the terminal run:
bundle install# or however you choose to handle your gem installations
- Create the
.envfile and then add your key/value information in with the following format:
You can now call your environment variables just as in method 1 by using:
4. Figaro (another Ruby gem)
Figaro aims to build upon what dotenv does by automating some of the steps. It handles the creation of a
config/application.yml file AND then adds it to the
.gitignore file as well.
- Add the gem to your
- In the Terminal run:
bundle exec figaro install
You can either choose to access the environment variables via the previously mentioned
Also you can add them to an initializer and have them handled for you like this:
<ClassName>.sid = ENV['twilio_app_sid']
<ClassName>.api_key = ENV['twilio_api_key']
*Note: Figaro also provides a handy way to push the configuration values up to Heroku from the configuration file via the following command:
figaro heroku:set -e production
5. 3rd Party Services
Some product environment hosting services, like Heroku, allow you to set your production environment variables via a GUI interface or via a command line tool. Since these implementations are normally unique to the service itself I’m not going to cover them here but I highly encourage you to look over the documentation of your hosting provider and see if that might be an option.
Like the hosting services, these implementations are all unique so you’ll have to look into them yourself to learn more.
As you can see you have a few different options of how to handle sensitive information in your application. While this is by no means an exhaustive list of options, it gives you the basic idea to start from. Securing this information might not seem like a big deal for a one-off side project but when it comes time to work on a client’s project or something sensitive for a company, knowing how to handle this information is vital.
Please reach out to me via the comments or contact form if you have any questions, ideas, or criticism!