Skip to main content
A private NPM registry lets you publish and consume packages that aren’t meant for the public registry. This is useful for sharing internal libraries across a team, distributing proprietary code between projects, or simply caching public packages behind your own infrastructure. Verdaccio is a lightweight, open-source NPM registry that you can self-host with Docker in minutes.

Why run a private registry?

  • Team packages — publish shared utilities, component libraries, or internal tooling that shouldn’t be exposed on the public registry.
  • Personal projects — maintain private packages across multiple personal projects without paying for a hosted registry.
  • Proxy caching — Verdaccio can act as a transparent proxy for the public registry, caching packages locally for faster installs and offline resilience.

Prerequisites

You need Docker and Docker Compose installed on your server:
docker --version
docker compose version

Setup

1

Create a project directory

Create a directory for your Verdaccio deployment and set up the subdirectories that will be mounted as volumes:
mkdir verdaccio
cd verdaccio
mkdir conf storage plugins
The conf directory will hold the Verdaccio configuration file. The storage directory will hold published packages. The plugins directory is for any optional plugins.
2

Add the config.yaml file

After starting the container for the first time, Verdaccio may exit with an error like cannot find config file or config file is missing. This happens because the ./conf directory is mounted but empty. You must create a config.yaml file inside ./conf before starting the container, or Verdaccio will fail to start.
Create ./conf/config.yaml with the following minimal configuration:
storage: /verdaccio/storage/data
plugins: /verdaccio/plugins

auth:
  htpasswd:
    file: /verdaccio/storage/htpasswd

uplinks:
  npmjs:
    url: https://registry.npmjs.org/

packages:
  '@*/*':
    access: $all
    publish: $authenticated
    proxy: npmjs

  '**':
    access: $all
    publish: $authenticated
    proxy: npmjs

server:
  keepAliveTimeout: 60

middlewares:
  audit:
    enabled: true

log: { type: stdout, format: pretty, level: http }
This configuration allows anyone to read packages, requires authentication to publish, and proxies missing packages from the public NPM registry automatically.
3

Create the Docker Compose file

Create a docker-compose.yml file in your project directory:
services:
  verdaccio:
    image: verdaccio/verdaccio
    container_name: 'verdaccio'
    networks:
      - node-network
    environment:
      - VERDACCIO_PORT=4873
      - VERDACCIO_PUBLIC_URL=http://npm.demo.com
    ports:
      - '10001:4873'
    volumes:
      - ./storage:/verdaccio/storage
      - ./conf:/verdaccio/conf
      - ./plugins:/verdaccio/plugins

networks:
  node-network:
    driver: bridge
Replace http://npm.demo.com in VERDACCIO_PUBLIC_URL with your actual domain or server IP. Verdaccio will be available on port 10001 of your host.
4

Start the registry

Start Verdaccio in detached mode:
docker compose up -d
Verify it’s running:
docker compose logs -f verdaccio
You should see Verdaccio report that it’s listening on port 4873. Open http://your-server:10001 in a browser to confirm the web interface is accessible.
5

Configure npm to use your registry

Point your npm client at the private registry. You can do this globally or per-project.Globally — affects all npm commands on your machine:
npm set registry http://your-server:10001
Per-project — add a .npmrc file at the root of your project:
registry=http://your-server:10001
To revert to the public registry at any time:
npm set registry https://registry.npmjs.org
6

Create a user and publish a package

Create an account on your registry:
npm adduser --registry http://your-server:10001
You’ll be prompted to enter a username, password, and email. Once registered, you can publish packages as you normally would:
npm publish --registry http://your-server:10001

Verifying package resolution

You can confirm that Verdaccio is correctly proxying public packages by installing any public package through your registry. The first request will fetch and cache it from the public NPM registry; subsequent requests will be served from your local cache.
npm install lodash --registry http://your-server:10001
Check the ./storage directory — you should see the cached package appear there.