Maintaining a Private NPM registry for your Organization with Sinopia–Private NPM server

In this post, we will take a quick dig at setting up our own private Node Package Registry with Sinopia.

“sinopia is a private/caching npm repository server”

Maintaining a private NPM for your organization/team is very helpful when you would like to share the code only with them and not the entire universe. You can develop and maintain all your organization specific projects and their components as node packages that can be reused.

If there are multiple teams working, each of them can upload their own reusable node modules to the private NPM and other teams can use them. For example a File upload component or an organization specific HTML5 boilerplate and so on. This way, when you need something all you have to do is run npm install my-h5bp , which will download the boilerplate for you.

So, let us get started.

Official Approach

The folks at NPM have given us a process on how we can replicate the NPM privately.

Screen Shot 2014-09-21 at 10.16.33 amYou can check out this blog post to achieve the same. But this process is quite complex.

Another enterprise solution for setting up your private NPM is NPME – NPM Enterprise. You can find more info on that here : npm Enterprise. A quick video

Other Approaches

There are couple of other solutions like Kappa and node-reggie, which enable you to set up a private NPM with few quick steps.

But some how I was drawn to sinopia for its quick installation, setup and the ease of use. Sinopia uses a file system to manage the registry. The best part about Sinopia is, it does not sync the public registry by default, but it will cache the packages only when downloaded for the first time. You can save some space on your server (with the fast growing public registry and all).

Setup and Configure Sinopia

Setting up Sinopia as mentioned earlier is pretty easy. You need to have Node installed on the machine, where you are setting up the private NPM. Open terminal/prompt and  CD  to the root folder


> cd /
$ cd ~

Inside the root directory, create a new directory named sinopia

mkdir sinopia && cd sinopia

Next, we will install sinopia globally. Run

npm install -g sinopia

(use sudo if needed)

Now, we will start the server run


If you are launching the server for the first time, you will be asked to create a config file. Select Yes.

Note : If you launch the server from a different folder and if the folder does not have the config file you will be asked this question again. (I do not know why!) So make sure you launch the server from the same folder, the one we have cd ‘ed into earlier.

Screen Shot 2014-09-21 at 11.09.19 am

Now, when you navigate to http://localhost:4873/  you will see a message like


Web interface is a work-in-progress right now, so it is disabled by default. If you want to play with it, you can enable it in the config file.

To enable the web interface, we need to tweak the config file. From the current folder, open theconfig.yaml file. Scroll to a section named the web and set enabled to true.

Screen Shot 2014-09-21 at 11.00.55 amKill the sinopia server and relaunch it. Now navigate to  http://localhost:4873  and you should see the web interface

Screen Shot 2014-09-21 at 11.02.35 amSweet right!!

[Important Step]

Now, from a client machine where the private NPM will be accessed from, you need to set the NPM registry URL pointing to our Private NPM server and not the public registry.

If your server and client are same, you can run

npm set registry http://localhost:4873

And if your server and client are on different machines, you need to run

npm set registry

In your config.yaml you can configure the host and port too. Navigate to the Advanced section and you can updated the config like

Screen Shot 2014-09-21 at 11.16.22 amKill sinopia and restart it. Now your web URL will be  http://localhost:2772. Reverting the port back to 4873, we will continue.

Setup User

By default there is an Admin user setup, which you can find under the users section in the config.yaml.

Screen Shot 2014-09-21 at 11.22.19 amThis is the default admin account and the sha1 encrypted password. I am not sure what this password is, so I will reset to admin$123.

For that, open a new terminal/prompt. Run node  then execute

crypto.createHash(‘sha1’).update(‘admin$123’).digest(‘hex’) and paste it back to the config file

Screen Shot 2014-09-21 at 11.29.11 amSave the config file after pasting the generated hash, restart sinopia and run

Screen Shot 2014-09-21 at 11.34.59 amThe password would be admin$123.

You are logged in!!

To restrict access to the private registry, you can run

npm set always-auth true

This way you can secure all your private packages (more on conditional securing in a moment).

Now, a new client who would like to access the registry would need to create an account by running

npm adduser –registry http://localhost:4873/

Provide user details and bam!! You have a newly authenticated account for your private registry

Screen Shot 2014-09-21 at 11.48.24 am Now you will see a new file created inside the sinopia folder

sinopia folder


sinopia  tree

|– config.yaml

`– htpasswd

0 directories, 2 files

The htpasswd file consists of the authentication data. It is better not to mess with this file.

Downloading packages

Now that we have everything setup, we will download our first package. Create a new folder named privateProj and open a new terminal/prompt inside this folder

Now run

npm init

to start a new node project. Next, we will install diskDB a node package for managing JSON files.  If you do notice your sinopia folder, you will see that there are only 2 files. The config and the htpasswd file. Now once we start pulling the packages, a new folder named storage will be created. You can configure the storage folder path in config.yml. Screen Shot 2014-09-21 at 11.59.23 am

From inside the privateProj run

npm install diskdb –save

And you should see

Screen Shot 2014-09-21 at 12.01.14 pmDo remember, diskdb is not in our private registry. Sinopia has fetched this package from the public repo. Now, if you see the sinopia folder, you will see

Screen Shot 2014-09-21 at 12.02.58 pmIf the public registry is offline or not available for some reason, sinopia will fetch the packages from the cache.  You can configure this behaviour in the uplinks section.

Screen Shot 2014-09-21 at 12.06.12 pmNow that we have diskdb installed in our privateProj, we will build a simple app and publish it to our private registry.

Build & Publish a Node module

You can check out my post Write your own Node Modules on how to create your own node modules and publish it.

Do note that as long as your registry URL is pointed to the private repo, the publish command would not save the package to the public registry.

Now, to build a sample node module/reusable component, we will create a folder named dband a file named app.js inside the privateProj folder.

Update the app.js as below



var db = require(‘diskdb’);

db = db.connect(‘db’, [‘fruits’]);

var fruits = [‘Apple’, ‘Mango’, ‘Orange’];;

var printFruits = function() {



// To test the app locally

// printFruits(); // << uncomment this

// and run

// $ node app.js

exports.printFruits = printFruits;

Now, our app is ready. We would like to share this app with our team, so they can reuse theprintFruits().

For that we would be publishing this app to our private registry. Run

npm publish

and you should see something like

Screen Shot 2014-09-21 at 12.20.02 pmThe user arvind does not have access to publish to our private registry. For this to work, we need to provide access. Open config.yaml and scroll down to the packages section and add the user name to allow_publish.Screen Shot 2014-09-21 at 12.23.18 pmSave the file and restart the sinopia server. Now when you publish you should see

Screen Shot 2014-09-21 at 12.25.16 pmAnd when you navigate to  http://localhost:4873 you should see

Screen Shot 2014-09-21 at 12.26.08 pm

Now, if you see the sinopia folder,

Screen Shot 2014-09-21 at 12.27.11 pm

Simple and easy right!!

Now, if someone wants to use your package all they need to do is run

npm install privateProj –save

The same way one would from the public registry and you should see

Screen Shot 2014-09-21 at 12.29.20 pm

And then in your project, you can directly use



var pp = require(‘privateProj’);


And run

node myApp.js

If you want to maintain a different “namespace” for your private packages, you can do so by prefixing your packages with your organization name or your project name and update theconfig.yaml like

Screen Shot 2014-09-21 at 12.56.19 pm

You can also setup a different storage for your private repos too.

That is all you need to setup your private NPM and manage packages.

Note : If you followed the above post on a local machine and wanted to revert your npm registry to the public one, execute

npm config set registry


npm config set registry

How to host Sinopia in IIS on Windows?


  "name": "iisnode-sinopia",
  "version": "1.0.0",
  "description": "Hosts sinopia in iisnode",
  "main": "start.js",
  "dependencies": {
    "sinopia": "^1.3.1"



process.argv.push('-l', 'unix:' + process.env.PORT);


<configuration> <system.webServer> <!-- indicates that the start.js file is a node.js application to be handled by the iisnode module --> <handlers> <add name="iisnode" path="start.js" verb="*" modules="iisnode" /> </handlers> <rewrite> <rules> <!-- iisnode folder is where iisnode stores it's logs. These should never be rewritten --> <rule name="iisnode" stopProcessing="true"> <match url="iisnode*"/> <action type="None"/> </rule> <!-- Rewrite all other urls in order for sinopia to handle these --> <rule name="sinopia"> <match url="/*" /> <action type="Rewrite" url="start.js" /> </rule> </rules> </rewrite> <!-- exclude node_modules directory and subdirectories from serving by IIS since these are implementation details of node.js applications --> <security> <requestFiltering> <hiddenSegments> <add segment="node_modules" /> </hiddenSegments> </requestFiltering> </security> </system.webServer> </configuration>


Sinopia Commands

npm publish (to publish package) or npm publish –tag <tag>

npm unpublish –force (to unpublish / delete package)

npm install / update (Installing packages (npm install, npm upgrade, etc.)

npm dist-tag add <package>@<version>

npm adduser {newuser}

npm search

Useful Links






Happy Coding Smile

Leave a Reply

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

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

Google photo

You are commenting using your Google 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 )

Connecting to %s