Managing Environment Variables with Global and dotenv Gems

Kurt Cunningham
Jan 12, 2018 · 3 min read

At Made by Munsters, our Rails projects use dotenv to load environment variables for development and test Rails servers. dotenv reads a file (by default, the appropriately named .env) that contains a simple list of name=value pairs and loads each as a new environment variable entry. For instance, a .env file with these contents:

SECRET_SERVICE_KEY = '123-opensesame'

dotenv would read that and populate Rails variables ENV['SERVER_URL'] and ENV['SECRET_SERVICE_KEY']. This discussion won't cover installing dotenv, but it's a simple process and you can read the project's installation instructions to get yourself started.

Because environment variables frequently hold confidential details, such as secret keys, those .env files shouldn't be checked into source control. That protocol works to keep secret keys secret, but architecture has some drawbacks:

  • No environment variable documentation is checked into source control. There isn’t an easy way to document important details about the variables, such as how they were derived or what format they need to appear in.
  • Environment variable references are spread out through the codebase; there is no consolidated list of environment variables in source control. This can be problematic when you’re trying to verify that a new deployment environment that doesn’t use a dotenv file (production environments running on Heroku, in our case) has the necessary environment variables configured.
  • Not easy to add common, non-secret values that don’t need to be hidden from source control, are OK to share among team members. For instance, default values for development environments that are shared by all team members.

Our solution to this problem is to enlist the help of another gem, Global. Global reads configuration details from YAML files, loading them into a namespace under the globally accessible Global module. It also supports ERB interpretation and environment-specific configuration.

With Global, we can now define a single environment configuration file that contains all of our environment variable references alongside their documentation. The above sample would look like this:

# Fully qualified server URL, including protocol and trailing slash.

# Secret service key. See Clay for help generating a new key to use
#in your local deployment.

I store this file in /config/global/env.yml, which means that the variable is contains are accessible in the Global.env namespace. So referring to the full server URL would look like Global.env.SERVER_URL.

Having ERB interpretation available in the configuration parsing also provides some opportunities to implement some extra features, such as default values for dev environments. If you wanted to make life easier for your fellow developers by having the server URL default to localhost:3000 in development environments, you could use this config file:

# Default values, shared by all environments.
# Fully qualified server URL, including protocol and trailing slash.

# Secret service key. See Clay for help generating a new key to use
# in your local deployment.

# Development-specific values. Overrides defaults.
# Default to localhost:3000 if not SERVER_URL is defined.
SERVER_URL: <%= ENV['SERVER_URL'] || 'http://localhost:3000/' %>

The setup gives you a complete list of environment variables your system needs to run, documentation of those variables right alongside their declaration, and optional environment-specific overrides.

Originally published at

Made by Munsters

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store