Managing Configurations in Node.JS apps with dotenv and convict

Sherry Hsu
3 min readJul 28, 2018

There are different phases of environment that an app will go through during development. During each phase, different database connection, environment URLs, API Keys etc are used. Usually it goes like:

    development ->      test     -> production
URL: localhost -> server.test -> production.server

We can store these configuration variables without any libraries but there are 2 excellent configuration libraries that can help us manage configurations in big Node.js applications: dotenv and convict.

Set environment variables with dotenv

Environment variables are global variables that are usually used to set application execution parameters.

dotenv sets the environment variables, process.env[VAR], for you based on the .env file. In the case where your .env file contains values that should not be revealed such as keys/secrets/passwords, the .env file should be included in the .gitignore to prevent someone from committing it to the git repository.

# Example take from dotenv documentation
# install dotenv

npm install dotenv
# server.js
# it automatically loads the environment variables defined in .env
require('dotenv').config()
# .env
NODE_ENV=dev
DB_HOST=localhost

Note that dotenv sets the global environment variables directly. If there are some configurations that we don’t want to save in the environment variables, we can use convict (or both)!

Setting configuration using convict

Convict is a robust configuration library that introduces configuration schema that provides more context on each config variable for each team member.

Setting configuration with convict
# Example take from convict documentation
# install convict
npm install convict
# config.js
const convict = require('convict');
// Define schemavar config = convict({
env: {
doc: "The application environment.",
format: ["production", "development", "test"],
default: "development",
env: "NODE_ENV"
},
db: {
host: {
doc: "Database host name/IP",
format: '*',
default: 'server1.dev.test'
},
name: {
doc: "Database name",
format: String,
default: 'users'
}
}
});
// Load environment dependent configuration
var env = config.get('env');
config.loadFile('./config/' + env + '.json');

// Perform validation
config.validate({allowed: 'strict'});
module.exports = config;
# server.js
const config = require('./config.js');
console.log(config.get('db.host')) // server1.dev.test

The configuration schema has a few properties that make the convict library robust. A few to note especially:

  • env: It will overwrite the setting’s default environment variables
  • arg: It will take in command-line arguments and overwrite default values or values derived from env
  • sensitive: If set to true, this value will be masked when config.toString() is called

Share Configuration details among team members

It is ok to leave a default value in the configuration variables such as NODE_ENV, URL. However, it is extremely dangerous to commit keys/ secrets/ passwords into git repository. In this case, the .env and .env.json files are not committed to the git repository.

How can we share keys/secrets/passwords among team members in a big team?

An easy way is to use the password managers such as 1Password or KeePass. 1Password is a sophisticated password managers that offer extensive functionalities such as access controls, 1-click filling passwords. Its Team&Business plans enable everyone in the team to add and share passwords.

KeePass is an open source and free password manager that save passwords into a database file. The saved database file can be placed on the cloud such as Dropbox which every team member has access to.

--

--

Sherry Hsu

A software engineer passionate about learning and growth