Install via Docker
docker run -d --name verdaccio \
--restart unless-stopped \
-p 127.0.0.1:4873:4873 \
-v verdaccio-storage:/verdaccio/storage \
-v ./conf:/verdaccio/conf \
verdaccio/verdaccio:6
Or with npm directly:
npm install -g verdaccio
verdaccio # runs on :4873, config at ~/.config/verdaccio/config.yaml
The config.yaml
# conf/config.yaml
storage: /verdaccio/storage
plugins: /verdaccio/plugins
web:
title: Internal Packages
primary_color: "#4f46e5"
auth:
htpasswd:
file: /verdaccio/storage/htpasswd
max_users: 100
# Where to proxy unknown packages
uplinks:
npmjs:
url: https://registry.npmjs.org/
timeout: 30s
cache: true
# Package access rules
packages:
'@mycompany/*':
access: $authenticated
publish: $authenticated
unpublish: $authenticated
# No proxy — these are internal-only
'**':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs # everything else falls through to public npm
listen: 0.0.0.0:4873
log: { type: stdout, format: pretty, level: info }
# Optional — persistent JWT tokens (so logins survive a restart)
security:
api:
jwt:
sign:
expiresIn: 90d
Restart Verdaccio. The web UI is at http://<host>:4873; sign in with npm adduser --registry http://<host>:4873 to create the first user.
Reverse proxy
# Caddy
npm.example.com {
reverse_proxy 127.0.0.1:4873
request_body { max_size 100MB }
}
Point clients at the public URL after this.
Use it as a developer
# Tell npm to use Verdaccio for everything
npm config set registry https://npm.example.com
# Or just for @mycompany packages, and stay on public npm for the rest
npm config set @mycompany:registry https://npm.example.com
# Log in
npm adduser --registry https://npm.example.com
# Prompts for username, password, email; saves token to ~/.npmrc
Publish an internal package
cd my-shared-lib
# package.json must scope to @mycompany
# {
# "name": "@mycompany/utils",
# "version": "1.0.0"
# }
npm publish
The package lands in Verdaccio, visible in the web UI under @mycompany/utils. Other team members install with npm install @mycompany/utils from their normal workflow.
The proxy behavior
When a client requests a package Verdaccio hasn't seen:
- Verdaccio asks the configured uplink (npmjs.org).
- Downloads the package tarball + metadata.
- Caches both locally.
- Serves to the client.
Subsequent installs of the same version are served from cache. Useful for offline CI / restricted networks / faster repeat installs in a team.
Authentication options
Beyond the bundled htpasswd:
- LDAP —
verdaccio-auth-ldap - GitHub OAuth —
verdaccio-github-oauth - GitLab —
verdaccio-gitlab - OIDC / Generic OAuth —
verdaccio-openidfor Authentik / Keycloak (see Authentik tutorial)
Install via npm into the Verdaccio container, reference in auth:.
Tokens for CI
Generate a read-only or publish token for CI:
npm token create --read-only
# Output: npm_********
# In CI:
echo "//npm.example.com/:_authToken=npm_********" >> ~/.npmrc
npm install
Tokens are revocable from the web UI; rotate per-CI-account as needed.
Storage management
The default file storage backend keeps everything under /verdaccio/storage/:
/verdaccio/storage/
htpasswd # bcrypt'd user creds
@mycompany/
utils/
package.json
utils-1.0.0.tgz
utils-1.0.1.tgz
react/ # cached from npmjs
package.json
react-18.0.0.tgz
react-18.1.0.tgz
For larger registries, swap the storage backend (S3, MinIO via plugin). For most teams, file storage is fine; restic backups on the directory covers it.
Verdaccio for other ecosystems
The npm registry shape is closer to "private store + cache for packages" than the npm CLI specifically. Equivalents exist for:
- Maven / Gradle (Java) — Reposilite (Kotlin, single-binary), Nexus Repository (heavier), JFrog Artifactory (commercial).
- PyPI (Python) — pypiserver, devpi, Bandersnatch (mirror).
- RubyGems — Geminabox.
- Docker / OCI — Distribution (the upstream Docker registry), Harbor (with auth, scanning), Cloudsmith / Artifactory for commercial.
- Helm — ChartMuseum, or use the OCI registry pattern.
- Multi-format — Nexus, Artifactory, Cloudsmith handle all of the above in one product (commercial).
For just npm + a small team, Verdaccio is the right size in 2026. For a polyglot fleet with serious package management requirements (vulnerability scanning, signed artifacts, multi-region replication), graduate to Nexus or a hosted service like Cloudsmith.
When Verdaccio isn't the right tool
- For high-availability registries serving an entire enterprise, Verdaccio's single-node story doesn't scale.
- For per-package vulnerability scanning + license tracking, look at Snyk + a heavier registry.
- For OCI / container images, use a dedicated container registry.
For "we want our internal JavaScript packages on infrastructure we control, plus a faster cache for public npm," Verdaccio installs in under five minutes and stays out of the way.