Update: My preferred way of hosting a private npm registry has changed. Use Nexus instead.

If you create a few node.js projects of decent size and complexity you’ll find yourself needing to share code between projects. Using npm is the easiest way to go about this, and it will allow you to easily write small modules that do one thing well.

You have a few options:

  1. Publish code to npm as public modules.
  2. Use the git repo url of a module as the npm install target.
  3. Setup a private npm registry with a proxy to the public npm registry.

Publishing a publicly available npm module to share internal code is a bad idea, especially if it’s code that you (or your employer) needs to keep closed source. Even if it is code that you’d like to open source, and have the ability to do so, make sure you actually want to be responsible for maintaining a project that other people will depend on.

Using git urls will work, but you lose the version number control that semver gives you. It can also become problematic when you have git repos that far larger than the deployable tarballs that are published to npm (see the pain caused by large files and node-tar).

The best option is to either run your own private npm registry, or pay for somebody to do it for you.

The current path of least resistance these days is to just pay nodejitsu to host a private npm registry for you. They take care of all the maintenance, plus I’ve found their public npm proxy to be faster than installing packages directly from npmjs.org.

npm, Inc is also developing their own private npm solution, npm enterprise, though it is still in the beta trial stages right now. I’m sure it’ll be a great solution, but would hesitate to jump in until you know what the pricing will be.

If you’d like to host your own private registry in house, my recommendation is to use sinopia.

Quick Start

The easiest way to test out sinopia is to do a local install (there’s no need to install the package globally).

mkdir private-npm
cd private-npm
npm install sinopia
./node_modules/.bin/sinopia

Config file doesn't exist, create a new one? (Y/n) Y
===========================================================
 Creating a new configuration file: "./config.yaml"

 If you want to setup npm to work with this registry,
 run following commands:

 $ npm set registry http://localhost:4873/
 $ npm set always-auth true
 $ npm adduser
   Username: admin
   Password: R0PFdXYYzw
===========================================================
 warn  --- Server is listening on http://localhost:4873/

Managing Multiple Registry Configs

You should now have your own private npm registry running. The last thing to consider doing is using some simple bash aliases to so you can switch between public and private npm registries.

First you want to move aside your existing .npmrc that references the public npm registry.

cp ~/.npmrc ~/.npmrc-public

Then follow the instructions above that sinopia outputs on the first run. It will result in your .npmrc pointing to the private registry. Then move aside your new private registry .npmrc as well.

cp ~/.npmrc ~/.npmrc-private

Finally set up the bash aliases to switch between the two configs.

alias npm-public='rm -f ~/.npmrc && ln -s ~/.npmrc-public ~/.npmrc'
alias npm-private='rm -f ~/.npmrc && ln -s ~/.npmrc-private ~/.npmrc'

Looking Ahead to NPM Scopes

Rather than having to rely on a single registry, npm 2.0.0 supports scoped packages. The blog post on Nodejitsu explains it in detail.

Being able to alias a registry to a scoped name (i.e. http://registry.foo.com -> @foo) means that you can still use the public npm registry for 3rd party modules, rather than needing a private registry that also proxies to the public registry.

Right now scoped packages aren’t widely supported, but the feature exists in the npm cli and gives npm a well defined route forward to supporting many registries to install from.