Managing Configurations in Node.JS apps with dotenv and convict
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.
# 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 variablesarg
: It will take in command-line arguments and overwrite default values or values derived fromenv
sensitive
: If set totrue
, 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.