GitHub recently released a new version of its search feature. Unfortunately, it quickly became obvious that the feature could be misused to locate data that wasn’t intended to be exposed publicly. Passwords, oAuth tokens, and private API keys are particularly common in source code, and well-crafted searches to find them were making the social media rounds almost immediately after the new feature was released.

Of course, this sort of thing is nothing new. Similar Google searches have been possible for years. However, GitHub currently seems to house a concentration of particularly sensitive secrets. Maybe that’s because it’s so easy to accidentally commit these things along with associated code with a quick git commit -a.

I’ve been working on a few Node.js projects hosted on Windows Azure lately, and one in particular is stored in a public GitHub repository but needs access to private oAuth keys. So, this topic is something I’ve been dealing with myself lately. Through that project, I’ve been fortunate enough to stumble onto a nice symbiosis between Azure and a Node.js module called nConf that solves the problem of storing secrets in my public repositories.

Adding nConf to your Node.js app

nConf is a simple, but handy, module by Charlie Robbins. As with any other npm module, adding nConf to your app is easy. A quick npm install nconf from your project’s root directory will do it:


You’ll see npm downloading nConf and its dependencies, and then you’ll be ready to start using the module in your code right away.

I can’t say enough good things about how well the folks at Joyent and Microsoft have made this work on Windows. I have a MacBook and I host this site on an Ubuntu VPS, but I still do the overwhelming majority of my serious development work on a Windows 8 desktop. In the early days, working with Node.js on my Windows desktop was tedious and painful, but things have changed significantly for the better during 2012. Kudos to everyone involved in making that happen.

Using nConf to read settings from a config file

With nConf installed, exposing configurable settings for your app is simple. For example, let’s say we want our app to have a configurable username and password. You might create a file called settings.json like this:

Then, you could pull those settings into your application with code like this:

That’s a handy way to read in settings from a config file, but this approach alone brings us right back the point where settings.json might accidentally get committed to a public repository.

Reading environment variables instead of a config file

Along with pulling settings out of a JSON file, nConf also supports reading arguments from environment variables. That’s particularly useful if your app is hosted on a PaaS like Azure that allows you to configure those environment variables through an interface that’s independent of your code.

For example, providing a username and password setting in this section of Azure’s “Configure” tab makes those settings available to Node as environment variables:


That’s great because nConf can read configuration from environment variables just as easily as a JSON file. All you need to do is a call nconf.env() instead of nconf.file():

By itself, that’s not particularly impressive. You could also read those environment variables via process.env.username and process.env.password, without any extra modules.

However, the beauty of nConf is that you can combine both approaches.

The best of both worlds

Using environment variables works pretty well once the code is deployed to Azure, but I think the simple config file is a lot more convenient when I’m developing locally. The best thing about nConf is that it supports reading settings from both locations, in the priority that you specify.

So, you can use a settings file locally, but supersede that with environment variables if they’re present (i.e. once deployed to Azure). To do that, you can chain nConf initialization calls to both .file() and .env():

Now, running this locally with the settings.json file from earlier will output “password123”, but deploying it to the Azure site with the app settings shown above will change the output to… a 500 error, of course.

This simple example code doesn’t handle HTTP requests, nor does it output HTTP responses, so running it on Azure doesn’t work. But, the password variable will be correctly initialized to “hunter2” instead of “password123” when running on Azure with the environment variables we set in the previous section.

Now, add settings.json to your .gitignore and you’ll never need to worry about pushing your local, potentially-sensitive, credentials to a public repository.