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