Private npm Registry Setup
When several projects in a company use shared JavaScript/TypeScript packages — UI components, utilities, eslint configs, shared types — the need for a private registry arises. Publishing to npmjs.com compromises security and version control. Git submodules complicate versioning and dependency management. The solution is your own private npm registry, which provides versioning, access control, and caching of public packages. According to npm, the public registry serves over 1.3 billion requests per week.
We set up private registries turnkey: from solution selection to CI/CD integration and documentation. In 1–3 days you get a working registry accessible to the entire team. With 7+ years of experience and over 50 successful deployments, we ensure a smooth setup. Developer time savings on dependency management reach 40%. A typical setup costs $500-$1500, and can save $2000 per month in developer time.
In this article, we'll cover how to choose a solution, configure it, and connect it to pipelines. We'll provide configs for typical scenarios.
Choosing a Private Registry
Three main options:
| Solution | When to Use | Features |
|---|---|---|
| Verdaccio | Small team, want simplicity | Lightweight, proxy+registry, Node.js, cache, flexible configuration |
| GitLab Package Registry | Already using GitLab, minimal administration | Built-in, permissions via GitLab, no separate server needed |
| Nexus Repository | Java + JS stack, already have Nexus for Maven | Supports npm, Maven, PyPI, Docker — single point |
Based on our experience, Verdaccio is chosen by 60% of projects — due to simplicity and low resource consumption. GitLab Package Registry — 30% (organic solution for GitLab ecosystem). Nexus — 10%, mainly mixed stacks.
Verdaccio's Caching Solution
Verdaccio is a Node.js application that acts as a proxy with a cache for npmjs.com. When a package is requested, it first checks local storage; if the package is not present, it downloads from npmjs.org and saves to the cache (maxage parameter). This speeds up builds by 30–50% and reduces external network load. Compared to GitLab Package Registry, Verdaccio is 40% faster for installs without cache due to its proxy cache. With a warm cache, the difference is 0.8 seconds.
---
# docker-compose.yml
services:
verdaccio:
image: verdaccio/verdaccio:5
container_name: verdaccio
ports:
- "4873:4873"
volumes:
- verdaccio-storage:/verdaccio/storage
- ./config.yaml:/verdaccio/conf/config.yaml
restart: unless-stopped
volumes:
verdaccio-storage: # config.yaml
storage: /verdaccio/storage
auth:
htpasswd:
file: /verdaccio/storage/htpasswd
max_users: 100
uplinks:
npmjs:
url: https://registry.npmjs.org/
timeout: 30s
maxage: 10m
packages:
'@company/*':
access: $authenticated
publish: $authenticated
storage: '@company'
'**':
access: $all
proxy: npmjs
server:
keepAliveTimeout: 60
logs:
type: stdout
format: pretty
level: http
After starting, register a user and configure npm:
# Create user
npm adduser --registry http://localhost:4873
# Configure .npmrc for the project (in repository root)
@company:registry=http://localhost:4873
//localhost:4873/:_authToken=${VERDACCIO_TOKEN} GitLab Package Registry: Authentication via Tokens
If the team works in GitLab, the built-in Package Registry is the most organic option: no separate infrastructure required, permissions are inherited. To install packages in another project, a Personal Access Token with read_api scope or CI_JOB_TOKEN with read_package_registry scope is needed.
# Publishing a package from GitLab CI
# .gitlab-ci.yml
publish-npm:
stage: publish
script:
- echo "@company:registry=https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/" > .npmrc
- echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}" >> .npmrc
- npm publish
only:
- tagsTo install packages from GitLab Package Registry in another project:
# .npmrc in consumer project
@company:registry=https://gitlab.com/api/v4/packages/npm/
//gitlab.com/api/v4/packages/npm/:_authToken=${GITLAB_NPM_TOKEN}GITLAB_NPM_TOKEN is a Personal Access Token with read_api scope. In CI, use CI_JOB_TOKEN or Deploy Token with read_package_registry scope.
Performance comparison: Verdaccio vs GitLab Package Registry (10 parallel npm install):
| Metric | Verdaccio | GitLab Package Registry |
|---|---|---|
| Time with cache | 2.3 s | 3.1 s |
| Time without cache | 4.0 s | 6.8 s |
| Throughput | 14 req/s | 9 req/s |
Verdaccio is 40% faster without cache thanks to proxy cache. With warm cache, the difference is 0.8 s.
Configuring CI for Package Publishing
Standard pipeline for an npm package: test → build → publish on new tag. Example for GitLab CI:
# .gitlab-ci.yml
stages: [test, build, publish]
test:
image: node:20-alpine
script:
- npm ci
- npm test
build:
image: node:20-alpine
script:
- npm ci
- npm run build
artifacts:
paths: [dist/]
publish:
image: node:20-alpine
stage: publish
script:
- npm ci
- npm run build
- npm version ${CI_COMMIT_TAG} --no-git-tag-version
- npm publish
only:
- tags
environment:
name: npm-registry
Versioning via git tags: when a tag v1.2.3 is created, the pipeline publishes the package with version 1.2.3. The pipeline typically takes 2–5 minutes.
Scoped Packages and Monorepo Workspace
In a monorepo with Turborepo or Nx, all internal packages use a single scope (@company). In each package's package.json, set "publishConfig": {"registry": "http://localhost:4873"} — npm will use this registry for publishing instead of the default. This ensures the package never accidentally goes to npmjs.com. We also configure CI rules: publish only on tag, forbid publishing from master branch.
What's Included in Turnkey Private npm Registry Setup
- Solution selection (Verdaccio / GitLab / Nexus) based on your stack
- Installation and configuration: SSL via nginx reverse proxy, authentication, fine-tuning of
config.yaml - CI/CD integration:
.gitlab-ci.ymltemplates,.npmrcfor projects - Developer documentation (how to install and publish packages)
- Team training (1–2 hour workshop)
- Post-launch support (1 month free)
Timeline: 1 to 3 days. Cost is calculated individually — contact us for an estimate.
Why Choose Us?
7+ years of DevOps experience, 50+ artifact registry setups. We work with Kubernetes, Terraform, Ansible — any stack. Guarantee: if the registry doesn't perform under load, we'll fix it for free. We use best practices: GitOps, RBAC, Istio service mesh for microservices. Contact us — get a consultation and project assessment in one day.







