Instalación de Verdaccio: Registro npm Privado

Verdaccio es un registro npm privado ligero que permite publicar, almacenar en caché y gestionar paquetes Node.js en tu propia infraestructura. Con soporte para proxy hacia el registro público de npm, control de acceso granular y despliegue sencillo con Docker, Verdaccio es la solución ideal para equipos que necesitan paquetes privados o una caché local para acelerar las instalaciones.

Requisitos Previos

  • Servidor Linux (Ubuntu 20.04+, Debian 11+ o CentOS 8+)
  • Node.js 18+ y npm (para instalación directa)
  • Docker y Docker Compose (para instalación con Docker)
  • Dominio o IP del servidor para el registro
  • Acceso root o sudo

Instalación con npm

# Instalar Verdaccio globalmente
npm install -g verdaccio

# Verificar la instalación
verdaccio --version

# Iniciar Verdaccio (crea la configuración en ~/.config/verdaccio/)
verdaccio &

# Comprobar que está escuchando
curl http://localhost:4873/

Crea el servicio systemd para que Verdaccio arranque automáticamente:

# Crear usuario dedicado
sudo useradd -r -s /sbin/nologin verdaccio
sudo mkdir -p /opt/verdaccio/{storage,conf}
sudo chown -R verdaccio:verdaccio /opt/verdaccio

sudo tee /etc/systemd/system/verdaccio.service << 'EOF'
[Unit]
Description=Verdaccio - Registro npm Privado
After=network.target

[Service]
Type=simple
User=verdaccio
ExecStart=/usr/bin/verdaccio --config /opt/verdaccio/conf/config.yaml
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now verdaccio

Despliegue con Docker

Docker es la opción más rápida para entornos de producción:

# Crear estructura de directorios
mkdir -p /opt/verdaccio/{storage,conf,plugins}

# Configuración inicial
tee /opt/verdaccio/conf/config.yaml << 'EOF'
storage: /verdaccio/storage
auth:
  htpasswd:
    file: /verdaccio/conf/htpasswd
    max_users: 50

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

packages:
  "@mi-empresa/*":
    access: $authenticated
    publish: $authenticated
    unpublish: $authenticated

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

server:
  keepAliveTimeout: 60

middlewares:
  audit:
    enabled: true

log:
  type: stdout
  format: pretty
  level: http
EOF

# Docker Compose
tee /opt/verdaccio/docker-compose.yml << 'EOF'
version: "3.8"

services:
  verdaccio:
    image: verdaccio/verdaccio:5
    container_name: verdaccio
    restart: unless-stopped
    ports:
      - "4873:4873"
    environment:
      - VERDACCIO_PORT=4873
    volumes:
      - ./storage:/verdaccio/storage
      - ./conf:/verdaccio/conf
      - ./plugins:/verdaccio/plugins
EOF

cd /opt/verdaccio && docker compose up -d
docker compose logs -f

Configura Nginx como proxy inverso con SSL:

sudo tee /etc/nginx/sites-available/verdaccio << 'EOF'
server {
    listen 443 ssl http2;
    server_name npm.tudominio.com;

    ssl_certificate /etc/letsencrypt/live/npm.tudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/npm.tudominio.com/privkey.pem;

    # Aumentar el tamaño para paquetes npm grandes
    client_max_body_size 100m;

    location / {
        proxy_pass http://127.0.0.1:4873;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/verdaccio \
  /etc/nginx/sites-enabled/verdaccio
sudo certbot --nginx -d npm.tudominio.com
sudo systemctl reload nginx

Configuración del Proxy y Caché

Configura Verdaccio para usar caché agresiva de paquetes públicos:

# /opt/verdaccio/conf/config.yaml - Configuración de uplinks y caché
uplinks:
  npmjs:
    url: https://registry.npmjs.org/
    cache: true         # Almacenar paquetes en caché local
    timeout: 30s
    maxage: 10m         # Tiempo de caché para metadatos
    max_fails: 3        # Intentos antes de marcar como caído
    fail_timeout: 5m

  yarn:
    url: https://registry.yarnpkg.com/
    cache: true

packages:
  # Paquetes privados de tu empresa - sin proxy a npm
  "@mi-empresa/*":
    access: $authenticated
    publish: $authenticated
    unpublish: $authenticated

  # Alcance compartido con equipo externo
  "@colaboracion/*":
    access: $authenticated
    publish: $authenticated
    proxy: npmjs

  # Todo lo demás se obtiene de npm y se almacena en caché
  "**":
    access: $all
    publish: $authenticated
    proxy: npmjs

# Configuración del servidor
server:
  keepAliveTimeout: 60

# Retención de caché (limpiar paquetes sin usar después de N días)
store:
  # Solo disponible con algunos plugins de almacenamiento
  maxAge: 2592000  # 30 días en segundos

Publicación de Paquetes Privados

Configura npm para usar tu registro privado:

# Configurar npm para usar Verdaccio
npm set registry https://npm.tudominio.com/

# O usar un fichero .npmrc por proyecto
echo "registry=https://npm.tudominio.com/" > .npmrc

# Para paquetes con scope, solo redirigir ese scope a Verdaccio
echo "@mi-empresa:registry=https://npm.tudominio.com/" >> ~/.npmrc

# Crear una cuenta en Verdaccio
npm adduser --registry https://npm.tudominio.com/

# Iniciar sesión
npm login --registry https://npm.tudominio.com/

Publica tu paquete privado:

# Verificar que el package.json tiene el scope correcto
cat package.json | grep '"name"'
# Debe ser: "@mi-empresa/mi-paquete"

# Publicar el paquete
npm publish --registry https://npm.tudominio.com/

# Instalar desde el registro privado
npm install @mi-empresa/mi-paquete

# Verificar que el paquete está disponible
curl https://npm.tudominio.com/@mi-empresa%2fmi-paquete

Autenticación y Control de Acceso

Verdaccio usa htpasswd por defecto. Para gestionar usuarios:

# Instalar herramienta htpasswd
sudo apt install -y apache2-utils

# Añadir un nuevo usuario al fichero htpasswd
htpasswd /opt/verdaccio/conf/htpasswd nuevo_usuario

# Crear el fichero desde cero con el primer usuario
htpasswd -c /opt/verdaccio/conf/htpasswd admin

# Ver usuarios actuales
cat /opt/verdaccio/conf/htpasswd

Control de acceso granular en la configuración:

# Gestión detallada de acceso por paquete
packages:
  # Paquetes críticos - solo el equipo de arquitectura puede publicar
  "@mi-empresa/core-*":
    access: $authenticated
    publish: arquitectura desarrollo
    unpublish: arquitectura

  # Paquetes UI - cualquier desarrollador puede publicar
  "@mi-empresa/ui-*":
    access: $authenticated
    publish: $authenticated

  # Paquetes públicos - acceso sin autenticación
  "utilidades-publicas":
    access: $all
    publish: $authenticated
    proxy: npmjs

Integración con CI/CD

Configura tu pipeline para usar el registro privado:

# GitHub Actions / Gitea Actions
jobs:
  build:
    steps:
      - name: Configurar npm para usar Verdaccio
        run: |
          echo "registry=https://npm.tudominio.com/" >> ~/.npmrc
          echo "//npm.tudominio.com/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc

      - name: Instalar dependencias
        run: npm ci

      - name: Publicar paquete
        if: github.ref == 'refs/heads/main'
        run: npm publish --registry https://npm.tudominio.com/
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Genera un token de autenticación para CI:

# Generar token npm para el pipeline
npm login --registry https://npm.tudominio.com/
# Introduce usuario, contraseña y email

# El token se guarda en ~/.npmrc - cópialo para los secretos del CI
grep "npm.tudominio.com" ~/.npmrc
# Resultado: //npm.tudominio.com/:_authToken=XXXXXXX

Solución de Problemas

Error 401 al publicar:

# Verificar que la sesión está activa
npm whoami --registry https://npm.tudominio.com/

# Volver a autenticarse
npm login --registry https://npm.tudominio.com/

# Comprobar permisos en la configuración de Verdaccio
grep -A5 "tu-paquete" /opt/verdaccio/conf/config.yaml

Verdaccio no hace proxy a npm:

# Verificar conectividad desde el servidor
curl https://registry.npmjs.org/express

# Ver los logs de Verdaccio
docker compose logs verdaccio | grep -i error

# Probar el uplink manualmente
curl https://npm.tudominio.com/express

Paquetes no se actualizan (caché obsoleta):

# Forzar la actualización del paquete en caché
npm install paquete@latest --registry https://npm.tudominio.com/ --force

# Limpiar el almacenamiento de un paquete específico
rm -rf /opt/verdaccio/storage/nombre-del-paquete

Conclusión

Verdaccio proporciona un registro npm privado completo que combina almacenamiento de paquetes internos con caché transparente del registro público. Su configuración sencilla, control de acceso granular y compatibilidad con los flujos de trabajo estándar de npm lo convierten en la solución perfecta para equipos que desarrollan con Node.js y necesitan privacidad, velocidad o control sobre sus dependencias.