Follow

Using nconf to configure a Node.js application

Introduction

Sometimes things vary from environment to environment. Like, we wear a tie to the office but try not to elsewhere. Similarly in Node.js, you might want configuration settings to change per environment. Some of these settings include IP address, port number, database configurations etc., that change from the development to production environment. The recommended approach for changing your app’s environment is by using the NODE_ENV environment variable.

Currently, Node.js does not have a standard way of managing config variables, but luckily there are a number of node modules that help you standardize this. One among them is the nconf package. Nconf provides a hierarchical Node.js configuration, with files, command-line arguments, and environment variables.

Sometimes we will refer configuration settings as settings/configurations.

Storing local configuration data

The simplest approach for storing the configuration for a Node.js app generally involves having an object stored as a JSON on the file system. This can be easily done using the JSON.parse and JSON.stringify  methods.

Let’s look at this simple example,

Saving Data

var fs = require('fs');
var myOptions = {
 name: 'Avian',
 dessert: 'cake',
 flavor: 'chocolate',
 beverage: 'coffee'
};

// Stringifying the data
var data = JSON.stringify(myOptions);
// Writing object into the json file
fs.writeFile('./config.json', data, function(err) {
 if (err) {
   console.log('There has been an error while saving your configuration data.');
   console.log(err.message);
   return;
 }
 console.log('Configuration saved successfully.')
});

Accessing the saved data

var fs = require('fs');
// Reading the object 
var data = fs.readFileSync('./config.json');
var myObj;
try {
  // Parsing the object
  myObj = JSON.parse(data);
  console.dir(myObj);
} catch (err) {
  console.log('There has been an error parsing your JSON.');
  console.log(err);
}

This works well for smaller applications, but as your application grows and runs on multiple environments, you’ll have to account for,

  1. Different values for different configuration options based on the environment (production, staging and dev).
  2. Configuration object getting too big, or configuration structure becoming too unwieldy.

Let’s see how nconf will make work easier and the code less error prone.

What can we do using nconf?

  1. Standard configurations can be kept in a separate file so that you can edit them without affecting the code.
  2. We can grab the environment variables and arguments to the script using built-in functions like nconf.env() and nconf.argv().
  3. Configurations can be accessed using standard JavaScript object syntax.
  4. Able to specify a different configuration file on the command line, so that you can easily switch between various configurations on different server environments.

Using nconf

Installation

npm install nconf

Example

Let’s consider the same example as given above and see how we’d access configuration settings from the config.json using nconf,

var nconf = require('nconf');
// Read the configuration settings from JSON file 
nconf.file({
  file: './config.json',
  // Setting the separator as dot for nested objects
  logicalSeparator: '.'
});
console.log(nconf.get('name')); // Prints Avian in the console.

While reading the configuration settings from JSON file, you can directly specify config file path or you can specify a different configuration file on the command line itself like below,

# npm start --<variable-name> <path/of/config/file>
npm start --config-file-path ./config_prod.json

Make sure that you don’t commit production configuration to your version control since it contains credentials that you want only certain people to view.

In the above example, reading configuration settings from JSON file can be written as below,

// Read the configuration from command line.
nconf.argv()

// Read the configuration settings from JSON file 
nconf.file({
  file: './config.json'|| nconf.get('config-file-path'),
  // Setting the separator as dot for nested objects
  logicalSeparator: '.'
});

Setting up a hierarchy of different sources

Using nconf, you can set up a hierarchy for different sources of your configuration.
The configuration source can be:

  • Command line arguments
  • Environment variables
  • File

Let’s take a look at the options available to you,

  • nconf.argv(options) Loads process.argv.
  • nconf.env(options) Loads process.env  into the hierarchy.
  • nconf.file(options) Loads the configuration data from a file into the hierarchy.
  • nconf.defaults(options) Loads the data in options.store into the hierarchy.
  • nconf.overrides(options) Loads the data in options.store into the hierarchy.

The order in which you load these configuration sources determines their priority in the hierarchy.

Example

Here’s an example to see how hierarchy works,

config.json

{
 "httpPort": "8000"
}

index.js

// Load nconf.overrides(options) on the top of the file before loading any other values
nconf.overrides({
  "httpPort": "4000"
});

// Your preffered config hierarchy
nconf.argv();

nconf.env();

nconf.file({
  file:'./config.json',
  // Setting the separator as dot for nested objects
  logicalSeparator: '.'
});

// Load nconf.defaults(options) at the bottom of your configuration file
nconf.defaults({
  "httpPort": "3000"
});

Lets try to understand this example:

{
 "httpPort": "8000"
}

In the config.json file the HTTP port is defined as 8000.

// Load nconf.overrides(options) on the top of the file before loading any other values
nconf.overrides({
  "httpPort": "4000"
});

In the index.js file we are loading overrides options.

The configurations defined in overrides options will take the highest priority and if you are going to load using overrides then this should be done before loading from any other source.

// Your preffered config hierarchy
nconf.argv();

nconf.env();

nconf.file({
  file:'./config.json',
  // Setting the separator as dot for nested objects
  logicalSeparator: '.'
});

Next, we are loading configurations from:

  • nconf.argv() – Command line arguments
  • nconf.env() – Environment variables
  • nconf.file() – From config.json file.
// Load nconf.defaults(options) at the bottom of your configuration file
nconf.defaults({
  "httpPort": "3000"
});

Finally, nconf also lets us load default configurations, the default configurations should be loaded last so that they are only used if values are not provided via any other mechanism.

Note that defaults will still respect priority order, i.e. If we try to load defaults  before loading other configurations then defaults will take higher priority.

// Loading nconf.defaults(options) before other sources
nconf.defaults({
  "httpPort": "3000"
});

// Your preffered config hierarchy
nconf.argv();
nconf.env();
nconf.file({
   file:'./config.json',
   logicalSeparator: '.'
});

In the above case nconf.get(‘httpPort’) will return 3000 since default configurations are being loaded first.

Note: Both nconf.defaults() and nconf.overrides() loads given configuration values into the configuration hierarchy. The first declared config value will always take precedence over others.

We can conclude that the configurations which are loaded first will take higher priority over others.

Why set it up this way?

The biggest benefit is to support multiple environments without having to manually change values on every deployment. Your command line arguments and environment variables will defer from server to server and need to be setup only once, whereas the config.json file might be pushed into your version control and remain same across servers. Values from config.json will only be loaded if certain values are not already present in the environment variables or not passed via command line arguments.

Summary

Nconf is a simple node module that provides us a robust way to get configuration information into our Node.js apps. It collects data from the host environment, command line arguments, and even multiple configuration files through a simple interface. This allows developers and admins to configure their application in any way they want based on the environment.

Posted By: Sindhusha B, Osmosee

Are you interested? follow us and get notified of new posts

3 thoughts on “Using nconf to configure a Node.js application

  1. hiteshlala
    at 1:34 am

    > “The config items that were loaded later will override any previous item ….”
    This is not what I found, when I tested earlier values took precedence.
    Eg. If my config.json is { test: ‘test’ } and I have process.env[‘test’] = ‘environment’.
    Then I do:
    nconf.env().file( ‘config.json’ );
    console.log( nconf.get( ‘test’ ) ); // outpus: environment

    but if I do:
    nconf.file( ‘config.json’ ).env();
    console.log( nconf.get( ‘test’ ) ); // outpus: test

    1. Admin
      at 4:02 pm

      @hiteshlala – You are right. Thanks for your input. We’ve now updated the blog to reflect the same, and added some more examples. Sorry for the confusion.

Leave A Reply