Dan Levy's Avatar DanLevy.net

Using Environment Variables in NodeJS

Using `dotenv`

Using Environment Variables in NodeJS

Handling Secrets & API Tokens Safely

Related Article: Protect Your Tokens

Let’s quickly recap the difference between secret and non-secret.



We’ll focus on dealing with 🔒 Secret keys using Environment Variables in this article.

Code examples are included below.

Overview

To safely access secrets in your NodeJS code:

  1. Replace hard-coded keys with environment variables. e.g. process.env.API_SECRET
  2. Use a library like dotenv along with a .env file. Add your previously hard-coded secrets to the .env file.
  3. Verify .env line in your .gitignore file!

DON’T create a .env file on deployed servers. Use your hosting services’ (e.g. Heroku, Netlify, AWS EC2) provided environment variable management tool: e.g. dashboard or command line.

Code Example

We’re going to define a few files.

  1. .env
  2. ./db/connection.js
  3. ./api/users.js

First, install the dotenv package.

Terminal window
npm install dotenv

Next, create a .env in the root of your project.

.env
PGDATABASE="postgres"
PGHOST="localhost"
PGPORT=5234
PGUSER="postgres"
PGPASSWORD="password"

NEVER commit .env file.

❌ Avoid creating .env on servers.

Check your Hosting Provider docs to set up environment variables.

To easily make sure your .gitignore has a .env line in it.

Terminal window
# Automatically update .gitignore
# Run in terminal:
[ "$(grep '^.env' .gitignore)" == "" ] && echo '.env' >> .gitignore
# note: no output will print

The ./db/connection.js provides a shared pg.Pool instance. It’ll be used to query the database.

./db/connection.js
require('dotenv').config(); // ✅ Load .env file
const pg = require('pg');
const {PGUSER, PGHOST, PGPORT} = process.env;
if (process.env.NODE_ENV === 'development')
console.log(`Connecting to ${PGUSER} @ ${PGHOST}:${PGHOST}`);
// ^^ only for showing debug connection vars
// pg automatically uses PG* env variables
module.exports = new pg.Pool();

The ./api folder contains interfaces to your tables/views.

Here’s an example ./api/users.js for the users table.

./api/users.js
const db = require('../db/connection.js');
module.exports = {
findUsername: function(username) {
return db.query('SELECT * FROM users WHERE username=$1', username);
}
};

* Every new development laptop or desktop should generate new access keys & tokens. If it’s not possible, use plenty of care sharing your .env (in cases where a service might invalidate all older keys, or you have a paid API’s limited access token.)

⚠️ Important: if necessary, always use a secure messaging service (preferably with expiring message support.)

Good luck and let me know if you have any questions! 🎉

Edit on GitHubGitHub