You are on page 1of 12

STARRHORNE HOWTO,RUBY

The Rubyists Guide to


Environment Variables

YOU'LLFIX
BUGS
BEFORE
YOURBOSS

If you want to be able to effectively manage web apps in

EVEN

development and in production, you have to understand

NOTICES

environment variables.

THEM

This wasnt always the case. Just a few years ago, hardly anyone

Whenpeople

was configuring their Rails apps with environment variables. But

dependonyour

then Heroku happened.


Heroku introduced developers to the12-factor appapproach. In
their12-factor app manifestothey lay out a lot of their best
practices for creating apps that are easy to deploy. The section on
environment variables has been particularly influential.

The twelve-factor app stores config in


environment variables (often shortened to env
vars or env). Env vars are easy to change
between deploys without changing any code;
unlike config files, there is little chance of
them being checked into the code repo
accidentally; and unlike custom config files, or
other config mechanisms such as Java System
Properties, they are a language- and OS-

appstowork,
youneed
Honeybadger.
Wegiveyou
complete
visibilityinto
production
problemsthe
momentthey
happen,andthe
toolsyouneed
tofixthem.

agnostic standard.

Take
chargeof
yourapps,
FREE

More Rubyists are using environment variables than ever. But


often its in a cargo-culty way. Were using these things without
really understanding how they work.
This post will show you how environment variables really work
and perhaps more importantly, how they DONT work. Well also
explore some of the most common ways to manage environment
variables in your Rails apps. Lets get started!

LATEST
TWEETS
The Rubyists Guide to
Environment Variables:
blog.honeybadger.io/ru
by-guide-env

2 DAYS AGO

Every process has its own set of


environment variables

Every program you run on your server has at least one process.

RECENT
POSTS

That process gets its own set of environment variables. Once it


has them, nothing outside of that process can change them.
An understandable mistake that beginners make is to think that
environment variables are somehow server-wide. Services like
Heroku sure make it seem likesetting the environment variables
is the equivalent of editing a config file on disk. But environment
variables are nothing like config files.

Working with
exceptions
in Pry

Every program you run on your server gets its own set of
environment variables at the moment you launch it.

The Rubyists
Guide to
Environment
Variables

Understanding the
Ruby Exception
Hierarchy

Plans and Pricing

Sign In

Every process has its own environment.

Environment variables die with their


process
Have you ever set an environment variable, rebooted and found
that it was gone? Since environment variables belong to
processes, that means whenever the process quits, your
environment variable goes away.
You can see this by setting an environment variable in one IRB
session, closing it, and trying to access the variable in a 2nd irb
session.

AngularJS for Rubyists

4 min to Spreed

When a process shuts down, its environment variables are lost

AngularJS for Rubyists

Sign up
for ouryou
Freeto
video
on Angular.
This is the same principal that
causes
losecourse
environment

You'll get a new video every day in your email for

variables when your serverfour


reboots,
or when you exit your shell. If
days.
you want them to persist across sessions, you have to store them
in some kind of configuration
filelike
.bashrc .
Email
Address

Sign Up

A process gets its environment variables


PO WE RE D BY D RI P

from its parent


Every process has a parent. Thats because every program has to
be started by some other program.
If you use your bash shell to launch vim, then vims parent is the
shell. If your Rails app uses imagemagick to identify an image,
then the parent of the identify program will be your Rails app.

Child processes inherit env vars from their parent

In the example below, Im setting the value of the $MARCO


environment variable in my IRB process. Then I use back-ticks to
shell out and echo the value of that variable.

Since IRB is the parent process of the shell I just created, it gets a
copy of the $MARCO environment variable.

Environment variables set in Ruby are inherited by child processes

Parents can customize the environment


variables sent to their children
By default a child will get copies of every environment variable
that its parent has. But the parent has control over this.
From the command line, you can use the env program. And in
bash theres a special syntax to set env vars on the child without
setting them on the parent.

Use the env command to set environment variables for a child


without setting them on the parent

If youre shelling out from inside Ruby you can also provide
custom environment variables to the child process without
littering up your ENV hash. Just use the following syntax with the
system method:

How to pass custom environment variables into Rubys system


method

Children cant set their parents


environment variables
Since children only get copies of their parents environment
variables, changes made by the child have no effect on the parent.

Environment variables are passed by value not by reference

Here, we use the back-tick syntax to shell out and try to set an
environment variable. While the variable will be set for the child,
the new value doesnt bubble up to the parent.

Child processes cant change their parents env vars

Changes to the environment dont sync


between running processes
In the example below Im running two copies of IRB side by side.
Adding a variable to the environment of one IRB session doesnt
have any effect on the other IRB session.

Adding an environment variable to one process doesnt change it for


other processes

Your shell is justa UI for theenvironment


variable system.
The system itself is part of the OS kernel. That means that the
shell doesnt have any magical power over environment variables.
It has to follow the same rules as every other program you run.

Environment variables are NOT the same

as shell variables
One of the biggest misunderstandings happens because shells do
provide their own local shell variable systems. The syntax for
using local variables is often the same as for environment
variables. And beginners often confuse the two.
But local variables are not copied to the children.

Environment variables are not the same as shell variables

Lets take a look at an example. First I set a local shell variable


named MARCO. Since this is a local variable, its not copied to any
child processes. Consequently, when I try to print it via Ruby, it
doesnt work.
Next, I use the export command to convert the local variable into
an environment variable. Now its copied to every new process

this shell creates. Nowthe environment variable is available to


Ruby.

Local variables arent available to child processes. Export converts the


local variable to an environment variable.

Managing Environment Variables


inPractice
How does this all work in the real world? Lets do an example:
Suppose you have two Rails apps running on a single computer.
Youre using Honeybadger to monitor these apps for exceptions.
But youve run into a problem.
Youd like to store your Honeybadger API key in the
$HONEYBADGER_API_KEY environment variable. But your two
apps have two separate API keys.
How can one environment variable have two different values?
By now I hope you know the answer. Since env vars are perprocess, and my two rails apps are run in different processes
theres no reason why they cant each have their own value for
$HONEYBADGER_API_KEY.
Now the only question is how to set it up. Fortunately there are a
few gems that make this really easy.

Figaro
When you install the Figaro gem in your Rails app, any values that
you enter into config/application.yml will be loaded into the ruby
ENV hash on startup.
You just install the gem:
1 # Gemfile
2 gem "figaro"

And start adding items to application.yml. Its very important that


you add this file to your .gitignore, so that you dont accidentally
commit your secrets.
1 # config/application.yml
2
3 HONEYBADGER_API_KEY: 12345

Dotenv
The dotenv gem is very similar to Figaro, except it loads
environment variables from .env, and it doesnt use YAML.
Just install the gem:
1 # Gemfile
2
3 gem 'dotenv-rails'

And add your configuration values to .env and make sure you git
ignore the file so that you dont accidentally publish it to github.
1 HONEYBADGER_API_KEY=12345

You can then access the values in your Ruby ENV hash
1 ENV["HONEYBADGER_API_KEY"]

You can also run commands in the shell with your pre-defined set
of env vars like so:
1 dotenv ./my_script.sh

Secrets.yml?
Sorry. Secrets.yml though cool doesnt set environment
variables. So its not really a replacement for gems like Figaro and
dotenv.

Plain old Linux


Its also possible to maintain unique sets of environment variables
per app using basic linux commands. One approach is to have
each app running on your server be owned by a different user.
You can then use the users .bashrc to store application-specific
values.

Working with
exceptions in Pry

HONEYBADGER.IOBLOG
Honeybadger.io Blog 2015
Powered by WordPress Themify WordPress Themes

You might also like