Learn Environment Variables

Why?

Avoid (accidentally) committing (exposing) your private keys, passwords or other sensitive details (by hard-coding in them in your script) to GitHub by storing them as environment variables.

Accidentally pushing API keys to GitHub can be an Expensive/Stressful Lesson: https://www.quora.com/My-AWS-account-was-hacked-and-I-have-a-50-000-bill-how-can-I-reduce-the-amount-I-need-to-pay

Up until now we hard coded our some of our Loopback Configuration variables, like our database information. One of the most common. Which was fine for learning purposes, but for a real app deployed on the internet we DO NOT want sensitive information in our GITHUB REPO.

There are plenty of horror stories online of exposed API Keys or other passwords left in a public github repository. Luckily github scans the repos and will warn you sometimes if it finds what it believes is an API KEY but other are looking for this information as well as told in this story

Accidentally pushing API keys to GitHub can be an Expensive/Stressful Lesson

Starbucks API Key Exposed

Environment variables are also useful for having a different configuration for development vs our deployed app For example we could have a test database that has a its own URL vs a production database that only the live deployed app interacts with.

What?

An environment variable is a KEY=value pair that is stored on the local system where your code/app is being run and is accessible from within your code. Just like we have variables in our JavaScript code, we have variables on a OS system level that we can use. These environment variables are only accessible if you have access to the machine and are helpful for not exposing our secret information but still allowing us to use it.

If you are new to "backend" development, you may not have encountered environment variables before, this quick guide will tell you all you need to know!

The Twelve-Factor App best practice recommends storing your app's configuration in the "environment", but what does that mean?

This simply means that you save any configuration both the values that are the same everywhere you run your app and the keys that change depending on where you are running the app, in the environment where you are running your app.

How?

List all the Default Environment Variables

For MAC/Linux USERS In your terminal type: printenv and then the enter key.

For WINDOWS in your terminal type: SET and then the enter key.

You should see something like this:

{
  TERM_PROGRAM: 'Apple_Terminal',
  SHELL: '/bin/bash',
  TERM: 'xterm-256color',
  TERM_PROGRAM_VERSION: '343.7',
  USER: 'n',
  PWD: '/Users/n/code/learn-environment-variables',
  LANG: 'en_GB.UTF-8',
  _system_arch: 'x86_64',
  _system_name: 'OSX',
  _: '/usr/local/bin/node'
}

This is a list of all the variables defined in your environment, in this case we are running printenv on a Mac using the "Terminal" app, if you are on Linux/Unix using Bash/etc. you will see something slightly different.

Node JS Environment Variables

Log the list of environment variables available to node.js in process.env

Node.js gives you access to the variables defined in your environment using the process.env global object.

In a new folder that is not in an existing project create a file called printenv.js and type/paste the following line in it:

console.log(process.env);

Run this script in your terminal:

node printenv.js

Adding Variables to your Environment

There are 3 ways to add variables to the environment where your app is running.

1. Command-Line Arguments

When you run your node program/app you can include settings as environment variables for example, try running the following:

PORT=1337 node printenv.js

Notice how the PORT variable is the first element displayed in the console? You are now able to access the PORT value in your node.js script by reference: process.env.PORT

including your config in the command you use to run your script/app gets cumbersome when you have lots of API Keys or Databases ...

2. Export the Variable to your Environment

An improvement on this command-line arguments is to export the variable in your terminal:

Type/paste this in your terminal window and tap enter:

export HELLO=WORLD

Now printenv or node printenv.js to see it printed! the HELLO key is now available in the process.env object try adding the following line to your printenv.js file:

console.log(">> Hello", process.env.HELLO);

Now run it in your terminal:

node printenv.js

What do you see?

>> Hello WORLD

Exporting your keys to your environment using export MY_VAR=HAI works but if you use a terminal that DOES NOT SAVE your variables across sessions, (e.g. if you close your terminal window!) you will have to keep exporting them!

Thankfully there is an easier way. If we had many environment variables we would have to type them in every time we ran the app as well. For Example:

PORT=8000 \
DB_URL=DB_URL=mongodb+srv:@cluster0-0vx31.mongodb.net \ 
NODE_ENV=production \
USER=John \ 
PASSWORD=1234 \
node .

As you can imagine this would be quite difficult to manage. Thankfully there's a 3rd (easier) way using an NPM library

NPM DOTENV

Using Dotenv

Installation

npm install dotenv --save

Usage

Loading your environment variables from a .env file is as easy.

Create a file named .env in the same folder as your printenv.js of your project and insert your key/value pairs in the following format of KEY=VALUE:

DB_HOST=127.0.0.1
DB_PORT=9200
DB_USER=TheSpecial
DB_PASS=EverythingIsAwesome

dotenv only works in javascript files, does not work in JSON Files

Now back in theprintenv.js we need to add some new code to use the .env file with the dotenv packagewe installed earlier.

require('dotenv').config()
console.log("Hello", process.env);

Git Ignore

The way we prefer to manage our Environment Variables on our development machines is using a .env file which gets loaded into our app once and adds any entries in the .env file to the process.env (global object). However we do not want to let git track the .env file because it has sensitive information. Luckily removing a file from being track by git is simple as telling git to IGNORE IT!

All the files git is not tracking are kept in the .gitignore file and, everything else not in this file is tracked by git.

When using the .env file we need to add it to our list of files in .gitignore so we can protect our sensitive information. To ignore the.env and haven't already, create a new repo by running the following command in this lessons folder.

git init

Now check the status of the repo with the following command:

git status

You will see the repository has the .env file listed after running git status. This means git is trying to track it. To stop it we need to add the.env file to the .gitnore file. If you don't have a .gitignore file in directory just create it.

Paste the following to the .gitignore file, note there already might be content in the file, but just the line below to it:

.gitignore
.env

After adding the file you should not see the .env file listed when you run git status.

Key Points

  • hard coding sensitive information in our code can expose that information, especially if that code is on a public github repository

  • environment variables are useful to protect sensitive information

  • environment variables will also let us use different values in different environments, production vs development

  • .env files with the dotenv NPM package make it easier to use and manage environment variables

  • .gitignore file lets us tell git what not track.

Last updated