Configuring Node.js Web Applications… Manually || Convict.js

There’s more than a few ways to configure node.js applications. I’ll discuss a few of them in this blog entry, so without mincing work, to configuring apps!

Solution #1: Build Your Own Configuration

Often this is a super easy solution when an application just needs a single simple configuration. Here’s an example I found that’s pretty clean that Noli posted on Stackoverflow to the question “How to store Node.js deployment settings/configuration files?“.

var config = {}

config.twitter = {};
config.redis = {};
config.web = {};

config.default_stuff =  ['red','green','blue','apple','yellow','orange','politics'];
config.twitter.user_name = process.env.TWITTER_USER || 'username';
config.twitter.password=  process.env.TWITTER_PASSWORD || 'password';
config.redis.uri = process.env.DUOSTACK_DB_REDIS;
config.redis.host = 'hostname';
config.redis.port = 6379;
config.web.port = process.env.WEB_PORT || 9980;

module.exports = config;

…then load that in with a require…

var config = require('./config')

The disadvantage is when the application gets a little bigger the configuration can become unwieldy without very specific, strictly enforced guidelines.

Solution #2: Use a Library/Framework Like Convict.js

The use of a library provides some baseline in which to structure configuration. In the case of convict.js it uses a baseline schema that then can be used to extend or override based on configurations needed for alternate environments. A first steps in setting up convict.js for the fueler project looks like this.

Setup a convict.js file:

var convict = require('convict');

// Schema
var conf = convict({
    env: {
        doc: "The App Environment.",
        format: ["production", "development", "test"],
        default: "development",
        env: "NODE_ENV"
    },
    port: {
        doc: "The port to bind.",
        format: "port",
        default: 3000,
        env: "PORT"
    },
    database: {
        host: {
            default: "someplace:cool",
            env: "DB_HOST"
        }
    }
});

// perform validation
conf.validate();

module.exports = conf;

The main two configuration values are the environment and port values. Others will be added as more of the application is put together, but immediately I just wanted something to put in the project to insure it works.

Next get the convict.js library in the project.

npm install convict --save

The save gets it put into the package.json file as a dependency. Once this is installed I opened up the app.js file of the project and added a require at the top of the file after the path require and before the express() call.

var path = require('path');
var config = require('./config');

var app = express();

In the app.set line for the port I changed the setting of the port to be the configuration parameter.

app.set('port', process.env.PORT || config.get('port'));

Now when I run the application, the port will be derived from the config.js file setting.

Now What Did I Do?

I’ll write more about this in the near future, but for now I’ve run into something not being setup right. I’m still working through various parts of customizing my setup. In the instructions for convict.js, which aren’t very thorough beyond the most basic use, is how to insure that the other environments are setup with *.json files. What I mean by this is…

I’ve setup a directory with three json files. It looks like this.

My Config Directory

My Config Directory

Each of these files (or at least one of the files) I would think, based on the instructions, get loaded and merged into configuration based on the code in my app.js as shown below.

var env = conf.get('env');
conf.loadFile('./config/' + env + '.json');

The order of override for the configuration values starts with the base config.js, then any *.json files override those config.js settings and any environment variables override the *.json set configuration variables. Based on that, unless of course I’ve missed something for this snippet of code, I should be getting the configuration settings from the *.json files.

My config file data looks like this. Since it is using cjson I went ahead and stuck comments in there too.

/**
 * Created by adron on 3/14/14.
 * Description: Adding test configuration for the project.
 */

{
    "port": {
        "doc": "The port to bind.",
        "format": "port",
        "default": 1337,
        "env": "PORT"
    }
}

Until later, happy coding, I’m going to dive into this and figure out what my issue is. In my next blog entry I’ll be sure to post an update to what the problem is.

Oh, and that fueler project. Feel free to ping me and jump into it.

3 thoughts on “Configuring Node.js Web Applications… Manually || Convict.js

  1. Hi Adron, it’s been a while :)

    I’ve done enough Node.js apps now that have all required some basic config and sanity checking that I wrote my own little object that deals with it.

    It gives me one place to specify config key names (DRY), automatically falls back to defaults when appropriate, and does some sanity checking for production deployments.

    http://pastebin.com/dye6xHsz

    In my app/server.js I call Config.checkConfig() to ensure things blow up if I haven’t set encryption keys etc.

    To read a config value somewhere in code I’d call Config.getConfig(Config.keys.port) (no need to write “port”)

    Example usage here: http://pastebin.com/7KVMD2bX

    Perhaps I should pull it out in to a little library, I’ve found it works well in practice.

    Btw that code is from a little side project I’m working on, planning poker for distributed teams – http://www.agilepoker.io/ – if you’re interested. It’s only running on one Heroku dyno atm so is pretty sluggish :)

    • Dig the planning poker game. Will take a look at that! :)

      Studying your config setup at the moment too. That’s interesting what you’re doing.

  2. In my different projects I have used nconf and etc modules that work pretty good for configurations. In addition to all the fallback stuff, these 2 are giving the possibility to access the nested configuration parameters using the following syntax:

    etc.get('database:url');

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s