Your Own Private Npm Repo With Sinopia
Oct 11, 2016
5 minute read

There are a number of reasons why hosting your own private npm registry is beneficial. It will allow you to host private npm modules and share them with your organization without exposing your modules to the public. Hosting your own npm repository will also allow you to cache public modules from the upstream public npm registry and will increase speeds when fetching dependencies using npm install after they have been cached.

The official documentation on running your own npm registry requires that you mirror all of the public npm registry and maintain a copy of the public npm registry database. This process is quite a bit of work, fortunately for us better solutions have been created by the wonderful node community. Sinopia is a tool which makes it very easy to host your own npm repo or proxy and allow for namespaced private modules for your organization.

Installing Sinopia

To run Sinopia, you will need a linux server. You can also install Sinopia on your local system if you you only intend to use it for yourself. However, if you plan on using Sinopia for your team or organization you will need to run it on a server you can all access.

Assuming you have a linux system with node installed, install Sinopia using npm.

npm install -g sinopia

Once installed, sinopia can started by simply running sinopia.

However, you will likely want to create a new system user for sinopia to run as. Sinopia will complain if you try to run it as root.

Create a new user for Sinopia by doing the following.

useradd sinopia
mkdir /home/sinopia
chown sinopia:sinopia /home/sinopia

Now, switch to the sinopia user we created and ensure you are in the users home directory.

su sinopia
cd /home/sinopia

Run sinopia, it will automatically generate a config file and give you a URL to access its web interface.

If you installed sinopia on your local system, you can access the web interface using http://localhost:4873. If you installed it on a server, simply replace localhost with the servers IP address or domain name.

The web interface will allow you to search through any private or cached packages that Sinopia has stored.

Configuring Sinopia

By default, the Sinopia config file can be found in sinopia/config.yaml. At the time of writing this, Sinopia does not generate a complete config file and only includes basic options in the generated config.yaml. However, you can find a complete config in their git repository here.

I won’t be touching on all of nopia’s configuration options because their example configuration to which I linked above is well documented. However, I will touch on a couple of options.

Namespace based access to private modules

You can specify different access policies based on module prefixes. Below is an example of how I am using this within my organization.

packages:
  'myorg-*':

    # Allow all users to read private packages.
    access: $all

    # Allow authenticated users to public packages.
    publish: $authenticated

    # No upstream proxy, all myorg-* packages will resolve internally.
    # proxy:

  '*':
    # allow all users (including non-authenticated users) to read and
    # publish all packages
    #
    # you can specify usernames/groupnames (depending on your auth plugin)
    # and three keywords: \"$all\", \"$anonymous\", \"$authenticated\"
    access: $all

    # allow all known users to publish packages
    # (anyone can register by default, remember?)
    publish: $authenticated

    # if package is not available locally, proxy requests to 'npmjs' registry
    proxy: npmjs

This packages configuration allows read access to all users, but only allows publishing of packages prefixed with myorg- to authenticated users. Notice the proxy option is also disabled here as we want packages prefixed with myorg- to be resolved locally and not proxied to the public NPM registry.

All other packages, ie. without the myorg- prefix can be read by all users, published by authenticated users, and any packages which cannot be resolved locally will be pulled and cached from the public npm registry.

User Management

At the time of writing this, Sinopia is configured to use its htpasswd authentication module by default. We have been unable to get this working within our organization and there is a known issue about it which you can find here.

We got around this authentication method by commenting out the htpasswd configuration options in config.yaml and using the users configuration object to set user accounts.

# Disabling htpasswd auth until this is fixed.
# https://github.com/rlidwka/sinopia/issues/329
# auth:
#  htpasswd:
#    file: ./htpasswd
#    # Maximum amount of users allowed to register, defaults to \"+inf\".
#    # You can set this to -1 to disable registration.
#    max_users: 1000
users:
  myuser:
    password: 226c1c467113553cd13789151d02b1839a12dc6b7
  anotheruser:
    password: e5e0384891356d06e1f49bfagfd2abdagfd9474a6

You can use the following within node to generate the password hashes for each user in your configuration. Simply supply your desired password to the update() method.

require('crypto').createHash('sha1').update('PASSWORD HERE').digest('hex');

Unfortunately, without using Sinopia’s htpasswd authentication mechanism using npm adduser to add a user to the private registry will not work. Until the above mentioned issue is resolved, users must be added manually to the config file. Once added to the config file, users can authenticate using npm adduser or npm login and can publish to your new private registry without issue.

Using your new private registry

To switch from the public NPM registry to your new private registry, you can use the following command.

npm set registry https://YOUR_REGISTRY_HERE

You can then authenticate to your private registry using:

npm adduser --registry https://YOUR_REGISTRY_HERE