# Learn Environment Variables

## *Why*?

![](https://3729111192-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LJF8uz6T7DhCLClK6jV%2F-LyNOY694-KcXLF_MN8A%2F-LyNQao6QBMe8MdUvk1A%2Fimage.png?alt=media\&token=b1edc73b-04c6-42e8-aa10-ea30f8275698)

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*](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)

> [Starbucks API Key Exposed](https://www.cisomag.com/indian-researcher-finds-starbucks-api-key-exposed-online/)

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.&#x20;

{% hint style="danger" %}
We never want to develop on a database or a server that is in production. &#x20;
{% endhint %}

## *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](http://12factor.net/config) ***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.<br>

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`&#x20;

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
```

{% hint style="info" %}
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!
{% endhint %}

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](https://www.npmjs.com/package/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
```

{% hint style="info" %}
dotenv only works in javascript files,  does not work in **JSON Files**
{% endhint %}

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

```javascript
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. &#x20;

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.

```javascript
git init
```

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

```javascript
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.&#x20;

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

{% code title=".gitignore" %}

```javascript
.env
```

{% endcode %}

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`](https://www.npmjs.com/package/dotenv) make it easier to use and manage environment variables
* `.gitignore` file lets us tell git what not track.
