Secure Environment Variables with Travis CI

While building a web app you'll often need to have access to different variables depending on the setup (or environment). For example, your local machine, the staging/testing server, and development servers are all different environments.

On each of these environments you might need different settings. On your local machine your app might connect to a localhost database, while staging and development connect to AWS DynamoDB or MongoDB Atlas. Environment variables give you the ability to have different settings across these environments.

Environment variables are typically stored in a .env file in your project directory consisting of key/value pairs. On your local machine the .env file contains key/values for your local setup, while the .env on staging and production contain the same keys, but values specific to their environment. Ex:

// Local .env
DB_URL = mongodb://localhost:27017/myapp

// Staging .env
DB_URL = mongodb://<NAME>:<PASSWORD>@cluster0-shard-00-00-pwdcu.mongodb.net:27017,cluster0-shard-00-01-pwdcu.mongodb.net:27017,cluster0-shard-00-02-pwdcu.mongodb.net:27017/<DATABASE>?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin

// Production .env
DB_URL = mongodb://<NAME2>:<PASSWORD>@cluster0-shard-00-00-pwdcu.mongodb.net:27017,cluster0-shard-00-01-pwdcu.mongodb.net:27017,cluster0-shard-00-02-pwdcu.mongodb.net:27017/<DATABASE>?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin

The connection settings in your app make use of these variables to connect to the different database depending on the environment. If you're in node, process.env.DB_URL would reference the DB_URL variable.

Git

Since the .env file needs to contain different values depending on the environment it's not recommended to commit it to git. The file might also contain sensitive data you don't want to share with the public. For these reasons most projects add .env to the .gitignore file so the .env file isn't tracked in git.

This setup requires you to manually update the .env file across environments when changes are made. That is, since the file isn't tracked in git any changes to the .env file are only made to your local version. Any new key/value pairs added to your .env file will need to have the same key and appropriate value added to the staging and production .env files. This can be done via ssh or through a hosted service's dashboard (like Heroku) in many cases.

What about Travis?

If you're using Travis CI to deploy and test your code Travis needs access to the same environment variables. The.travis.yml config file accepts a env key for adding environment variables:

env:
  DB_URL = mongodb://<NAME>:<PASSWORD>...

but this completely defeats the purpose of untracking the .env file in git as your private info is now available to the public in the .travis.yml file.

Thankfully Travis allows for encrypting environment variables, allowing you to add environment vars to .travis.yml without giving away sensitive data.

First, install the travis gem:

gem install travis

In your project directory run:

travis encrypt DB_URL=super_secret

This will return an encrypted string which can be added to the project's .travis.yml file.

There's also a --add option which will add the secure key to your .travis.yml file for you:

travis encrypt DB_URL=super_secret --add env

The .travis.yml file will now contain an entry of:

env:
  secure: MBxG/gsqeyONzA7wbWKACzv...

Travis will decrypt this into the original key/value pair of:

DB_URL=super_secret

Once the encrypted environment variable is added to the .travis.yml file you'll commit your changes and carry on with your normal process. Travis now has access to your environment variables and they'll remain secret from others even if your project repo is public. More info and options available in the Travis CI environment variables docs.

Comments