How to set up a private npm registry verdaccio in docker with reverse proxy nginx setup?

What is verdaccio?

Verdaccio is a simple, zero-config-required local private NPM registry. No need for an entire database just to get started. Verdaccio comes out of the box with its own tiny database, and the ability to proxy other registries (eg., also introduces caching the downloaded modules along the way. For those who are looking to extend their storage capabilities, Verdaccio supports various community-made plugins to hook into services such as Amazon's S3, Google Cloud Storage or create your own plugin.

Verdaccio Setup

Directory setup

Create two directory storage and config.

sudo chown -R 10001:65533 storage
sudo chown -R 10001:65533 config

Docker compose

Create a docker-compose.yml file with the following content.

version: "2.2"
    image: verdaccio/verdaccio
    restart: unless-stopped
      - VERDACCIO_PORT=4873
    tty: true
      - ./storage:/verdaccio/storage
      - ./config:/verdaccio/conf

Create user

Inside the config directory, create a file htpasswd. Generate username and password from and then copy the content to htpasswd.


Create a file config/config.yml with the following content.

storage: /verdaccio/storage
  enable: true
  primary_color: "#098aff"
    - npm
    - yarn
  showInfo: false
  showFooter: false
    file: /verdaccio/conf/htpasswd
#   Prevent anyone from setup account
    max_users: -1
    access: $authenticated
    publish: $authenticated
    unpublish: $authenticated
    proxy: npmjs
    access: $authenticated
    publish: $authenticated
    proxy: npmjs
log: { type: stdout, format: pretty, level: http }

For more detail, please visit

Start verdaccio

docker-compose pull
docker-compose up -d

We can visit localhost:4873.

Reverse proxy setup

Nginx setup

HTTP setup

upstream verdaccio {
    server verdaccio_relative_path:4873;
    keepalive 8;

server {
    listen 80 default_server;
    access_log /var/log/nginx/verdaccio.log;
    charset utf-8;

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;
      proxy_set_header X-NginX-Proxy true;
      proxy_pass http://verdaccio_v4_root;
      proxy_redirect off;

HTTPS setup

server {
    listen 80;
    return 302$request_uri;

server {
    listen 443 ssl http2;

    ssl_certificate     /etc/nginx/cert.crt;
    ssl_certificate_key /etc/nginx/cert.key;

    ssl on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_set_header    Host $host;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto $scheme;
        proxy_pass          http://verdaccio_v4_root;
        proxy_read_timeout  600;
        proxy_redirect off;

Now restart the nginx. we can now visit

Publish package

In a directory:

npm init

We can change the package name in package.json to include a scope.

  "name": "@my/hello"


Now login to our private npm registry.

npm login --registry

Publish the package

npm publish --registry

Or specify the registry in package.json.

    "registry": ""
npm publish

Install package

In a directory, create a file .npmrc with the following content.



npm login --registry

Install package

npm install package-name

Mike Mai
Mike Mai   Brooklyn, New York
I am full-stack web developer, passionate about building world class web applications. Knowledge in designing, coding, testing, and debugging. I love to solve problems.