--- title: "Cómo instalar Verdaccio como registro npm privado en Ubuntu" description: "Despliega Verdaccio con Docker en Ubuntu 24.04 como registro npm privado con HTTPS, publica paquetes con scope, cachea npmjs y úsalo desde tu CI con un token." category: "Herramientas de Desarrollo" language: es source: https://cubepath.com/es/docs/herramientas-de-desarrollo/instalacion-de-verdaccio-registro-npm-privado updated: 2026-09-25 --- # Cómo instalar Verdaccio como registro npm privado en Ubuntu Verdaccio es un registro npm ligero y autoalojado. Sirve para publicar paquetes privados de tu organización y, a la vez, actuar como proxy con caché del registro público `registry.npmjs.org`, de forma que las instalaciones repetidas sean más rápidas y no dependan de Internet para los paquetes ya descargados. En este tutorial desplegarás Verdaccio 6 con Docker Compose en Ubuntu 24.04, lo publicarás detrás de Nginx con HTTPS, publicarás un paquete con scope y configurarás un pipeline de CI para usarlo. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS y al menos 1 GB de RAM, por ejemplo un VPS de CubePath. - Un usuario no root con privilegios `sudo`. - Docker Engine y el plugin de Docker Compose instalados desde el repositorio oficial de Docker. - Nginx y Certbot instalados (`sudo apt install nginx certbot python3-certbot-nginx`). - Un subdominio como `npm.your_domain` con un registro DNS A apuntando a la IP del servidor. - Node.js y npm en la máquina desde la que publicarás paquetes (tu equipo de trabajo). En los ejemplos, sustituye `npm.your_domain` por tu dominio y `@your_company` por el scope de npm que usará tu organización. ## Paso 1: Crear la estructura de directorios Verdaccio guarda su configuración en `conf/` y los paquetes (y el fichero de usuarios) en `storage/`. Crea ambos directorios: ```bash sudo mkdir -p /opt/verdaccio/{conf,storage,plugins} ``` La imagen oficial ejecuta Verdaccio con el usuario de UID `10001` y GID `65533`, no como root. Asigna la propiedad de los directorios a ese usuario para que pueda escribir en ellos: ```bash sudo chown -R 10001:65533 /opt/verdaccio ``` ## Paso 2: Escribir la configuración de Verdaccio Crea el fichero de configuración: ```bash sudo nano /opt/verdaccio/conf/config.yaml ``` ```yaml storage: /verdaccio/storage plugins: /verdaccio/plugins web: title: Registro npm de your_company auth: htpasswd: file: /verdaccio/storage/htpasswd max_users: -1 uplinks: npmjs: url: https://registry.npmjs.org/ timeout: 30s maxage: 10m max_fails: 3 fail_timeout: 5m packages: "@your_company/*": access: $authenticated publish: $authenticated unpublish: $authenticated "**": access: $authenticated publish: $authenticated proxy: npmjs max_body_size: 100mb log: type: stdout format: pretty level: http ``` Las claves importantes son: - `auth.htpasswd.max_users: -1` desactiva el registro libre de usuarios con `npm adduser`. Las cuentas las crearás tú en el paso 4. - `uplinks.npmjs` define el registro público como origen. `maxage` indica cuánto tiempo se consideran frescos los metadatos cacheados antes de volver a consultarlos. - El bloque `@your_company/*` no tiene `proxy`, así que esos paquetes solo pueden venir de tu registro. Así nadie puede suplantar un paquete interno publicando uno con el mismo nombre en npmjs. - El bloque `**` cubre el resto de paquetes y los obtiene de npmjs a través de la caché. Con `access: $authenticated` solo los usuarios con cuenta pueden descargar, lo que evita que el servidor se convierta en un proxy abierto. - `max_body_size` sube el límite de tamaño de las peticiones para permitir publicar paquetes grandes. Asegúrate de que el fichero pertenece al usuario del contenedor: ```bash sudo chown 10001:65533 /opt/verdaccio/conf/config.yaml ``` ## Paso 3: Arrancar Verdaccio con Docker Compose Crea el fichero de Compose: ```bash sudo nano /opt/verdaccio/docker-compose.yml ``` ```yaml services: verdaccio: image: verdaccio/verdaccio:6 restart: unless-stopped ports: - "127.0.0.1:4873:4873" volumes: - ./conf:/verdaccio/conf - ./storage:/verdaccio/storage - ./plugins:/verdaccio/plugins ``` El puerto `4873` solo escucha en `127.0.0.1`: el acceso público pasará por Nginx con HTTPS. Arranca el contenedor: ```bash cd /opt/verdaccio sudo docker compose up -d ``` Comprueba que responde localmente: ```bash curl -s http://127.0.0.1:4873/-/ping ``` ```output {} ``` Si no obtienes respuesta, revisa los logs con `sudo docker compose logs verdaccio`. Un error `EACCES` indica que los permisos del paso 1 no se aplicaron. ## Paso 4: Crear los usuarios Con `max_users: -1`, los usuarios se añaden directamente al fichero `htpasswd`. Instala la utilidad `htpasswd`: ```bash sudo apt install apache2-utils ``` Crea el primer usuario con cifrado bcrypt (`-B`). La opción `-c` crea el fichero, así que úsala solo la primera vez: ```bash sudo htpasswd -B -c /opt/verdaccio/storage/htpasswd your_user ``` Para añadir más usuarios después, repite el comando sin `-c`. Devuelve la propiedad del fichero al usuario del contenedor: ```bash sudo chown 10001:65533 /opt/verdaccio/storage/htpasswd ``` Verdaccio relee el fichero `htpasswd` cuando cambia, así que no hace falta reiniciarlo. ## Paso 5: Publicar Verdaccio con Nginx y HTTPS Crea el bloque de servidor: ```bash sudo nano /etc/nginx/sites-available/verdaccio ``` ```nginx server { listen 80; listen [::]:80; server_name npm.your_domain; 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-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` La cabecera `X-Forwarded-Proto` es necesaria: Verdaccio la usa para generar las URL de descarga de los paquetes con `https://`. Sin ella, npm recibiría enlaces `http://` a los tarballs. Activa el sitio y recarga Nginx: ```bash sudo ln -s /etc/nginx/sites-available/verdaccio /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx ``` Si usas UFW, abre HTTP y HTTPS, y después obtén el certificado: ```bash sudo ufw allow 'Nginx Full' sudo certbot --nginx -d npm.your_domain ``` Comprueba el acceso por HTTPS: ```bash curl -s https://npm.your_domain/-/ping ``` ```output {} ``` ## Paso 6: Configurar npm en tu equipo A partir de aquí, trabaja en tu equipo de desarrollo. Inicia sesión en el registro. La opción `--auth-type=legacy` fuerza el inicio de sesión con usuario y contraseña, que es el que admite el plugin `htpasswd`: ```bash npm login --registry https://npm.your_domain/ --auth-type=legacy ``` ```output npm notice Log in on https://npm.your_domain/ Username: your_user Password: Logged in on https://npm.your_domain/. ``` npm guarda un token en `~/.npmrc`. Confirma que la sesión funciona: ```bash npm whoami --registry https://npm.your_domain/ ``` ```output your_user ``` Tienes dos formas de usar el registro: - **Solo para tu scope.** Los paquetes `@your_company/*` se resuelven contra Verdaccio y el resto contra npmjs directamente: ```bash npm config set @your_company:registry https://npm.your_domain/ ``` - **Para todo.** Todos los paquetes pasan por Verdaccio y se cachean en tu servidor: ```bash npm config set registry https://npm.your_domain/ ``` Para fijar el comportamiento por proyecto, guarda la misma línea en un fichero `.npmrc` en la raíz del proyecto, por ejemplo `@your_company:registry=https://npm.your_domain/`, y haz commit de él. Nunca hagas commit de un `.npmrc` que contenga tokens. ## Paso 7: Publicar e instalar un paquete privado Crea un paquete de prueba con el scope de tu organización: ```bash mkdir hello-lib && cd hello-lib npm init --scope=@your_company -y echo "module.exports = () => 'hola desde Verdaccio';" > index.js ``` Publícalo en tu registro: ```bash npm publish --registry https://npm.your_domain/ ``` ```output npm notice Publishing to https://npm.your_domain/ with tag latest and default access + @your_company/hello-lib@1.0.0 ``` Comprueba que el registro lo conoce: ```bash npm view @your_company/hello-lib --registry https://npm.your_domain/ ``` El paquete también aparece en la interfaz web de `https://npm.your_domain` tras iniciar sesión. Para instalarlo en otro proyecto que tenga el `.npmrc` con el scope configurado, basta con `npm install @your_company/hello-lib`. Para verificar la caché de npmjs, consulta un paquete público a través de Verdaccio: ```bash npm view express version --registry https://npm.your_domain/ ``` Después de instalarlo alguna vez desde el registro, en el servidor verás su directorio en `/opt/verdaccio/storage/express/`. ## Paso 8: Usar el registro desde CI/CD En CI no hay sesión interactiva, así que el pipeline debe recibir un token. Usa el que npm guardó al iniciar sesión, idealmente con un usuario dedicado para CI creado como en el paso 4: ```bash grep npm.your_domain ~/.npmrc ``` ```output //npm.your_domain/:_authToken=eyJhbGciOi... ``` Guarda el valor tras `_authToken=` como secreto en tu sistema de CI con el nombre `NPM_TOKEN`. Después, añade al repositorio un `.npmrc` que lea el token de una variable de entorno. npm sustituye `${NPM_TOKEN}` por su valor al ejecutarse: ```ini @your_company:registry=https://npm.your_domain/ //npm.your_domain/:_authToken=${NPM_TOKEN} ``` Un ejemplo para GitHub Actions o Gitea Actions: ```yaml name: publish on: push: branches: [main] jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 - run: npm ci - run: npm publish env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} ``` ## Solución de problemas **`npm publish` devuelve 401 o 403.** Comprueba la sesión con `npm whoami --registry https://npm.your_domain/`. Si la sesión es correcta, revisa que el nombre del paquete encaje con un bloque de `packages` cuyo `publish` incluya a tu usuario. Recuerda que Verdaccio no permite volver a publicar una versión ya existente: incrementa la versión con `npm version patch`. **`npm publish` devuelve 413 Request Entity Too Large.** El paquete supera `client_max_body_size` en Nginx o `max_body_size` en Verdaccio. Sube ambos valores, recarga Nginx y reinicia Verdaccio con `sudo docker compose restart`. **Los paquetes públicos no se descargan.** Comprueba que el servidor alcanza npmjs con `curl -sI https://registry.npmjs.org/` y revisa los logs con `sudo docker compose logs verdaccio --tail 50` para ver errores del uplink. ## Conclusión Has desplegado Verdaccio con Docker, protegido con HTTPS y autenticación, y lo has usado para publicar un paquete privado y cachear paquetes de npmjs. Como siguientes pasos, puedes limitar quién publica en cada scope indicando nombres de usuario concretos en `publish` en lugar de `$authenticated`, programar copias de seguridad del directorio `/opt/verdaccio/storage` y apuntar todos tus pipelines al registro para acelerar las instalaciones.