Building your own private NPM registry

Esslam Ben Ramadan
6 min readAug 3, 2020

--

Photo by Viktor Juric on Unsplash

Building a private NPM registry can seem like a daunting task but when broken down into smaller chunks it all becomes easier to understand.

Link to the GitHub repository if you just want to explore the code yourself.

Prerequisite

  • Verdaccio
  • Node
  • Docker
  • Your choice of hosting service

The Config

Verdaccio lets you get up and running fairly quickly but it would benefit you more to run it using a config file that allows us to modify the default behaviour. This will allow us to enable plugins and extend features such as authentication.

WARNING!! Do not panic, let’s work through this together.

  • Storage will be the storage location for our packages
  • Plugins we can ignore for now and you can explore as your requirements become more apparent.
  • Auth/Authentication is simply how we will choose to authenticate users that want to access our registry. Set up is done here, the default auth is based on htpasswd and is built-in. You can modify this behaviour via plugins.
  • Uplinks are one of my favourite features of Verdaccio as it allows the system to fetch packages from remote registries when those packages are not available locally.
  • Packages allow us to set the permission levels for the different types of packages we can register.
  • Logs is the logging system that will print out lots of useful information based on processing Verdaccio runs.

I’ve intentionally left out descriptions for each of the child properties as I don’t want to hit you with a wall of text. I simply want to pique your interest so that you may discover the rest for yourself.

Docker

Before we get started with docker I just wanted to run through a couple of things. I prefer to run this in a container environment, as opposed to a server somewhere with Node because it gives me so much more control. I can amend my environment image for things such as node versions and our service-specific tooling, Verdaccio. I know that this approach will work anywhere that supports docker.

Your folder structure should now look like this.

Current Config

At this point, we will start looking at Docker, so I’m assuming you have some basic knowledge. In regards to Verdaccio we have all we need to get started for local setup using the CLI tool, the process has been described here.

What we will do instead is set up a docker-compose config that we can then run with a docker-compose up instead of having to remember all the CLI variables we need to pass.

docker-compose.yml

This is our basic docker-compose setup, you can update the port here if you want to expose it on something different. Next just run the below, which will spin up a docker container using the Verdaccio image and our specific config options in the config file.

docker-compose up

Depending on what port you set you should see a log similar to the below.

Successful docker container spun up

And upon hitting http://localhost:4873 you will be met by:

Congratulations you have a full working private NPM registry running on your machine. 👏

Running it in the cloud

Now that we are able to run the project locally we can start working towards getting it deployed on a server so that it can be accessed by others. Our first concern when deploying to a server should be security.

The entire point in setting up a private registry is because you need something a little bit more bespoke which can be locked down so that only users with the correct credentials or whitelisted IP addresses can access the registry. Our default setup has no secure authentication in place, but it is set up so that anybody can create an account and pull our repositories.

The reason I’m sidetracking this bit is that depending on your intended use case the set up will be different. For the sake of covering all angles, I will set up our current registry so that only users I create can access the registry, pull from it and publish to it.

Updating config file

Let’s update the auth part in our config.yml file so that our htpasswd plugin will now look for a htpasswd file for its login details and we will set max_users to -1 which will disable registration.

auth:
htpasswd:
# Look for this htpasswd for login credentials
file: /conf/htpasswd
# Setting this to -1 so that registration is disabled
max_users: -1

We will also update access levels so only authenticated users can pull or publish npm repositories.

access: $authenticated
publish: $authenticated

So our new config should look a little like this. Please note I only kept the “**” package which is basically a catch-all for any package type.

Updated Config

Let’s deploy it

I’m going to be using Digital Ocean for my hosting provider, if you follow the referral link below for $100 worth of credit, if you wanted to test this out. You can choose your own provider and follow similar steps.

https://m.do.co/c/55a5402ce6fc

Inside of Digital Ocean I will create a new docker droplet. You can do this by

  1. Clicking the green create button top right.
  2. Click on the marketplace tab and select or search for docker and select.
  3. Choose the most basic plan.
  4. Next, you will pick whatever region is best for yourself and leave the Choose Volume and VPC sections untouched.
  5. In the authentication section, choose which is your preferred way to authenticate your access to the server.
  6. That’s it you can now create the droplet.

The droplet should be active now and on your dashboard, you will see your newly created droplet and its IP address. Go ahead and copy the IP address and ssh into your server.

Depending on how you set up the droplet you might need to enter the password you set.

Once you’re in your server go ahead and git clone your repository or clone mine. You should now see a copy of your project inside of your server. Next, you need to cd into the conf folder and create a new file called htpasswd. Inside this file add the credentials of the user account you want to use when accessing the registry. These credentials can be generated using any htpasswd generator. I used this one.

htpasswd generation

Once generated copy the given text and add it to your htpasswd file.

Generated details

Save this file and return back to the root of your project inside of the server. Run docker-compose up and tada!

Docker instance of verdaccio running on server

To visit your registry simply visit your droplet IP with the chosen port inside your docker config. http://111.11.11.11:4873 ← fake link :)

Once on the page, you should notice that the register option has disappeared but you should be able to login using the details you added into the htpasswd file.

Publishing

The final part of our adventure is how to actually publish an NPM repository to our new registry. Run the below and sign in using your Verdaccio details.

npm adduser --registry http://111.11.11.11:4873

Then cd to any project you want to publish and run

npm publish --registry http://111.11.11.11:4873
Verdaccio package published example

To install make sure you are logged in if not just run and fill in your credentials. You should then be able to install the package you published in addition to the proxy allowing us to install normal NPM packages.

--

--