npm Private Modules with Heroku

Yesterday npm released a feature called private modules. It let’s you publish to their module registry (npmjs.com) but keep your modules private. The old way of achieving private modules without running your own registry was convoluted, didn’t work well and required you commit and push your app tokens into your source code (gross). The new way, from npm, let’s you publish private modules just like normal modules and simply copy and paste your token into Heroku’s environment variables to keep it safe.

The general steps are:

  1. Sign up for private modules if you haven’t already yet (it’s $7 a month, why haven’t you?)
  2. Login to npm from the CLI
  3. Publish your private module to npm
  4. Setup .npmrc files for your project folders
  5. Create an environment variable on Heroku

Step 1: Sign up

Go to https://www.npmjs.com/private-modules and click sign up. Fill out the card details and click submit. First step done!

Step 2: Login to the CLI

After signing up you will need to login from the CLI (even if you have before) to sync up your new account info. Just run

$ npm login

Put in your username, password, and email, and then you’re off to step 3.

Step 3: Publish your first private module

Now that you’re signed up and logged in you can publish a private module. I’m going to assume here that you know how to make an npm package already. If not there’s tons of other tutorials on the interwebz.

The only difference between a normal npm package and a private npm package as far as your package is concerned is really the name. So if you have "name":"foobar"as your package name, you will need to change it to "name":"@yourusername/foobar". But, that’s it. Now you can run the normal npm publish command from your package’s directory/repo. That will publish it to, in this example’s case: https://www.npmjs.com/package/@yourusername/foobar

You can then require it in your other project’s package.json files just like any other module:

"dependencies": {
 "@yourusername/foobar": "1.2.3"
 },

Step 4: Setup project .npmrc files

This is probably the only real sort of confusing part. It’s not too complicated, but it may be slightly confusing if you’ve never done anything like this before.

When you logged in on Step 2 a file, ~/.npmrc, was created or updated. The file most likely contains something like:

//registry.npmjs.org/:_authToken=00000000-0000-0000-0000-000000000000

NOTE: The 0s above will be your token. This is not a session token and will not expire unless you change your password. Don’t worry if you are using a shared private module account for your organization (p.s. real org accounts are coming soon!) that other users logging in will invalidate the token or anything.

What you’re going to do now is copy that .npmrc file into project directories you want to use private modules with. If your helloworld app, the code you’re pushing to Heroku, uses your @yourusername/foobar module than helloworld’s project folder is the place you want to put your new .npmrc file. Now, copy and delete (cut) the auth token out and replace it with ${NPM_TOKEN}. Your file will now look like this:

//registry.npmjs.org/:_authToken=${NPM_TOKEN}

For local development you’re going to need to have this NPM_TOKEN environment variable set somewhere. On OS X and Linux with Bash you can simply open your .bash_profile and add (replacing the 0s with your token):

export NPM_TOKEN="00000000-0000-0000-0000-000000000000"

then refresh your terminal like

source ~/.bash_profile

You are now all set to npm install your private repos locally in a way that works on Heroku. Now onto the final step.

Step 5: Adding the environment variable to Heroku

The final step assumes that since you’re using Heroku you have the Heroku CLI tool. If not you can install it via their package installer or you can do it through their site. Anyway, just run this where, again, 0s are your token and helloworld is your Heroku app’s name:

heroku config:set NPM_TOKEN=00000000-0000-0000-0000-000000000000 --app=helloworld

That’ all! That wasn’t so bad was it. Adding more private modules to your project is now as simple as publishing them and requiring them in your project’s package.json file.