-
Notifications
You must be signed in to change notification settings - Fork 3
rails environment variables
Last updated 12 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.
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.
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.
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.
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="myname@gmail.com"
You’ll have to open a new shell or restart your terminal application to continue.
The Unix shell can be a headache, especially when used in combination with 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 an alternative to using the Unix shell that only requires a few lines of code in your Rails application to set environment variables. Use the alternative approach when you don’t want to set environment variables in the Unix shell.
This technique takes advantage of Ruby’s ability to set environment variables as well as read them. 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.
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/local_env.example.yml. Change the filename if the file exists (or create the file if it doesn’t), so you have 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.
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 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.
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.
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.
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 GMAIL_USERNAME=myname@gmail.com
If you have multiple environments on Heroku:
$ heroku config:add GMAIL_USERNAME=myname@gmail.com --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.
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.
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.