trevorblackman.dev

Documentation

Private NPM Registry

A guide on setting up a private NPM registry with Verdaccio and Docker.

This guide covers how to:

  • Set up a private NPM registry using Verdaccio and Docker
  • Log in to your private NPM registry
  • Publish a package
  • Download a package
  • Grant download access to specific users
  • Restrict anonymous registrations and manually manage users
  • Point scoped packages to your private NPM registry

1. Setting Up Verdaccio with Docker

Project Structure

Create a directory named private-npm-registry or a name you prefer:

private-npm-registry/
  conf/
    config.yaml
  storage/
  docker-compose.yml
  • config.yaml: Verdaccio configuration file
  • storage/: Holds published packages
  • docker-compose.yml: Docker configuration used to launch Verdaccio

Configuring Verdaccio

Create conf/config.yaml with the following:

storage: /verdaccio/storage

auth:
  htpasswd:
    file: ./htpasswd
    algorithm: bcrypt

packages:
  "@my-scope/*":
    access: $all
    publish: $authenticated

log:
  type: stdout
  format: pretty
  level: http

Notes:

  • $all allows anyone to download packages.
  • $authenticated allows only logged-in users to publish.
  • The registry hosts only packages under the @my-scope/* namespace unless you change the rule.

Caution: Verdaccio requires config.yaml, not config.yml. See the Verdaccio configuration docs for more options.

Docker Compose Configuration

Create docker-compose.yml:

version: "3.8"

services:
  verdaccio:
    image: verdaccio/verdaccio:latest
    ports:
      - 4873:4873
    volumes:
      - ./conf:/verdaccio/conf
      - ./storage:/verdaccio/storage

This setup:

  • Uses the latest Verdaccio Docker image
  • Exposes port 4873
  • Persists data using mounted volumes

Starting Your Registry

From the project root:

docker compose up

Your private NPM registry will be available at http://localhost:4873.

2. Logging In

Log in to your registry:

npm login --registry http://localhost:4873
  • You will be prompted for a username and password.
  • The first login automatically registers a new account.
  • Credentials are stored in your ~/.npmrc file.

Helpful commands:

npm whoami --registry http://localhost:4873
npm logout --registry http://localhost:4873

3. Publishing a Package

To test publishing, create a sample package.

  1. Create and enter a folder.
mkdir hello-world && cd hello-world
  1. Initialize the project.
npm init

Name the package @my-scope/hello-world.

  1. Add an index.js file.
module.exports = function () {
  console.log("Hello World! From @my-scope/hello-world");
};
  1. Publish your package.
npm publish --registry http://localhost:4873

4. Downloading a Package

Install from your registry:

npm install @my-scope/hello-world --registry http://localhost:4873

By default, $all users can download this package. To restrict access, update the configuration as shown below.

5. Granting Access to Specific Users

Update conf/config.yaml with a package-specific rule:

packages:
  "@my-scope/private-*":
    access: admin user-a user-b
    publish: admin
  • admin can publish and download.
  • user-a and user-b can download only.
  • Others have no access.

Built-in groups:

GroupDescription
$allAnyone, including anonymous users
$authenticatedLogged-in users only

Verdaccio does not support custom groups. Users must be listed explicitly. See this Stack Overflow reference for more detail.

6. Restricting Anonymous Registrations

To disable public signups and manage accounts manually, update the auth section of config.yaml:

auth:
  htpasswd:
    file: ./htpasswd
    algorithm: bcrypt
    max_users: -1

Then manually create users by generating encrypted credentials with a tool such as the HTPasswd Generator, and copy the generated output into conf/htpasswd.

7. Scoped Packages Configuration

To make the NPM client automatically use your registry for scoped packages, add this to your ~/.npmrc:

@my-scope:registry = http://localhost:4873

That lets you run:

npm install @my-scope/hello-world

without passing --registry each time.

8. Next Steps

Future improvements may include:

  • Running the registry behind a reverse proxy
  • Using HTTPS with a domain such as https://npm-registry.my-company.com

Resources