Skip to content

rails environment variables

Daniel Kehoe edited this page Dec 14, 2012 · 11 revisions

Rails Environment Variables

by Taylor Mock and Daniel Kehoe

Last updated 14 December 2012

Setting Rails environment variables. Using ENV variables in Rails, locally and with Heroku. A guide for developers using the example apps from the RailsApps project. Others may find it helpful as well.

Environment Variables

Rails applications should be “turnkey”; that is, deployed anywhere without modifying code. But many applications require configuration of settings such as email account credentials or API keys for external services. You can pass local configuration settings to an application using environment variables.

Operating systems (Linux, Mac OS X, Windows) provide mechanisms to set local environment variables, as does Heroku and other deployment platforms.

Keeping Environment Variables Private

Remote git repositories such as GitHub are a place to store and share code. If your project is open source, any developer will have access to your code. You don’t want to share email account credentials or private API keys with the public. If you’re collaborating on a team with a private git repository, your team members will share your code. Your local settings may not be suitable for all members of the team. In general, you shouldn’t save your local environment variables to a shared git repository.

Gmail Example

Consider an application that uses Gmail to send email messages. Access to Gmail requires a username and password for access to your Gmail account. In your Rails application, you will need to configure these credentials in the file config/environments/production.rb. A portion of the file might look like this:

config.action_mailer.smtp_settings = {
  address: "smtp.gmail.com",
  port: 587,
  domain: "example.com",
  authentication: "plain",
  enable_starttls_auto: true,
  user_name: ENV["GMAIL_USERNAME"],
  password: ENV["GMAIL_PASSWORD"]
}

You could “hardcode” your Gmail username and password into the file but that would expose it to everyone who has access to your git repository. Instead obtain an environment variable with ENV["GMAIL_USERNAME"].

Ruby will replace ENV["GMAIL_USERNAME"] with an environment variable. The variable can be used anywhere in a Rails application.

Let’s consider how to set local environment variables.

Option One: Set Unix Environment Variables

If you’re familiar with Unix, you’ve likely had experience setting environment variables. Unix environment variables are typically set in a file that is read when starting an interactive shell (the ~/.bashrc file for the bash shell).

Are you using a bash shell? Use echo $SHELL to find out. For a bash shell, edit the ~/.bashrc file and add (for our Gmail example):

export GMAIL_USERNAME="[email protected]"

You’ll have to open a new shell or restart your terminal application to continue.

It’s important to learn to use the Unix shell if you’re commited to improving your skills as a developer. But troubleshooting shell problems can be difficult, especially when using rvm, the Ruby Version Manager, or when the application is launched in nonstandard ways. For example, the Passenger web server runs as a different user and may not have access to the same environment variables as your login account.

We’ll show you two alternatives to using the Unix shell that only require a few lines of code in your Rails application to set environment variables. Use an alternative approach when you don’t want to set environment variables in the Unix shell.

Option Two: Use the Figaro Gem

The figaro gem offers an ideal alternative to setting environment variables in the Unix shell.

If you’re using one of the RailsApps example applications or you have generated a starter application using the Rails Composer tool, you’ll find a file named config/application.yml. This file was added by the figaro gem and contains key/value entries for each environment variable you may need. Each entry is commented out. Remove the comment character if you want to override environment variables from the Unix shell or set the environment variables using the config/application.yml file.

Option Three: Use a local_env.yml File

Like the figaro gem, this technique takes advantage of Ruby’s ability to set environment variables as well as read them. The figaro gem has additional features and we recommend it. However, if you want to understand how to set environment variables from within your Rails application, or you don’t want to add the figaro gem to your application, you may want to consider this implementation.

We’ll create a simple file that contains key/value pairs for each environment variable using the standard YAML file format. We’ll make sure this file is listed in the .gitignore file so it isn’t checked into the git repository. And we’ll add some code to the config/application.rb to read the file and set the environment variables before anything else is configured in the Rails application.

The local_env.yml File

Create a file config/local_env.yml:

# Rename this file to local_env.yml
# Add account settings and API keys here.
# This file should be listed in .gitignore to keep your settings secret!
# Each entry gets set as a local environment variable.
# This file overrides ENV variables in the Unix shell.
# For example, setting:
# GMAIL_USERNAME: 'Your_Gmail_Username'
# makes 'Your_Gmail_Username' available as ENV["GMAIL_USERNAME"]
GMAIL_USERNAME: 'Your_Gmail_Username'

If you are working on a team and you wish to share your configuration, you can copy this file for your collaborators to use.

Set .gitignore

If you have created a git repository for your application, your application root directory should contain a file named .gitignore (it is a hidden file). Be sure your .gitignore file contains:

/config/local_env.yml

This prevents the config/local_env.yml file from being checked into a git repository and made available for others to see.

Rails Application Configuration File

Rails provides the config/application.rb file for specifying settings for various Rails components. We want to set our environment variables before any other settings. Rails provides a config.before_configuration method to do so. See the RailsGuide Configuring Rails Applications for more.

Find the following code at the end of the config/application.rb file:

# Version of your assets, change this if you want to expire all your assets
    config.assets.version = '1.0'

and add this code after it:

config.before_configuration do
  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
  end if File.exists?(env_file)
end

The code opens the config/local_env.yml file, reads each key/value pair, and sets environment variables.

The code only runs if the file exists. If the file exists, the code overrides ENV variables set in the Unix shell. If you prefer to set environment variables in the Unix shell, don’t create the config/local_env.yml file.

Using Environment Variables

Use ENV["GMAIL_USERNAME"] anywhere in a Rails application. Your application won’t know if it was loaded from the config/local_env.yml file or from the Unix shell.

Distinguishing Development From Test Environments

Occasionally you’ll want to use different account credentials or API keys for test and development environments.

Give the variables different names, for example:

GMAIL_USERNAME_DEV: 'Your_Gmail_Username_For_Development'
GMAIL_USERNAME_TEST: 'Your_Gmail_Username_For_Tests'

and use the variables conditionally:

if Rails.env.development?
  config.action_mailer.smtp_settings = {
    user_name: ENV["GMAIL_USERNAME_DEV"]
  }
end

if Rails.env.test?
  config.action_mailer.smtp_settings = {
    user_name: ENV["GMAIL_USERNAME_TEST"]
  }
end

if Rails.env.production?
  config.action_mailer.smtp_settings = {
    user_name: ENV["GMAIL_USERNAME"]
  }
end

This approach works with either the config/local_env.yml file or environment variables obtained from the Unix shell.

Setting Environment Variables on Heroku

Heroku is a popular choice for low cost, easily configured Rails application hosting. See the article Heroku and Rails for details.

Heroku provides a simple mechanism for setting environment variables. After creating your Heroku app, set Heroku environment variables to provide the same data your application obtains from your local shell environment.

For example, for Gmail:

$ heroku config:add [email protected]

If you have multiple environments on Heroku:

$ heroku config:add [email protected] --remote staging

You can check that everything has been added correctly by running:

$ heroku info --app myapp

where “myapp” is the name of your Heroku application.

Notice that you don’t use the config/local_env.yml file. Your .gitignore file should prevent it from getting added to the git repository. It won’t exist when you deploy to Heroku and your application will obtain environment variables from the Heroku configuration table.

Other Approaches

There are other approaches to setting environment variables in Rails.

Tammer Saleh suggests a similar approach using the Rails environment.rb file in his blog posting, Managing Heroku environment variables for local development.

Brandon Keepers offers the dotenv Ruby gem that handles loading environment variables in development. The dotenv gem loads environment variables from a .env file.

Foreman is a tool for starting and configuring multiple processes in a complex application. Foreman will load environment variables from a .env file.

There are numerous gems such as yettings that set application configuration variables or other constants from a YAML file and allow access the to values with a method such as AppConfig.gmail_username. This approach is best used for constants that can be checked into a git repository and are not specific to a particular deployment. Local environment variables are better suited to deployment-specific configuration settings.

Did You Like the Article?

Was this useful to you? Follow rails_apps on Twitter and tweet some praise. We’d love to know you were helped out by the tutorial.

Any issues? Please leave a comment below.

Clone this wiki locally