Configurando um registro NPM interno/privado com Verdaccio

Fábio J L Ferreira
6 min readSep 12, 2021

--

O Verdaccio é uma alternativa simples, flexível e open-source de Registro NPM local. Em determinados contextos boa parte das empresas e organizações acabam optando por ter seus próprios servidores de registro, seja por questões ligadas a privacidade/segurança ou simplesmente por um motivo estratégico.

❗️Pré-requisitos

Para o pleno aproveitamento desta material é necessário que você tenha familiaridade com as seguintes tecnologias e ferramentas:

  • Docker
  • NPM, Yarn ou PNPM (ao longo deste material utilizarei NPM, porém, os outros gerenciadores também são totalmente compatíveis)

👨‍💻 Preparando o ambiente

O processo de configuração e subida do ambiente é muito simples e rápido!

Configuração

Vamos criar e acessar nosso diretório de trabalho:

mkdir verdaccio && cd verdaccio

Agora crie um diretório chamado conf e dentro do mesmo um arquivo config.yaml com o seguinte conteúdo:

storage: /verdaccio/storage
plugins: /verdaccio/plugins
web:
title: Verdaccio
auth:
htpasswd:
file: /verdaccio/storage/htpasswd
#max_users: -1
uplinks:
npmjs:
url: https://registry.npmjs.org/
packages:
'@*/*':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs
'my-company-*':
access: $all
publish: $authenticated
unpublish: root
'**':
access: $all
proxy: npmjs
middlewares:
audit:
enabled: true
logs: { type: stdout, format: pretty, level: http }

Vamos entender algumas das configurações mais relevantes:

  • auth.htpasswd:
  • => file: este arquivo armazena os metadados referente aos usuário cadastrados;
  • => max_users: define o número máximo de usuários que podem se registrar. Quando definido como -1 desabilita o registro de novos usuários.
  • uplinks: cria alias para outros servidores de registro. No exemplo acima criamos um alias para o repositório padrão do NPMJS (entenderemos seu uso mais adiante);
  • packages:
  • => @*/*: qualquer pacote que case com essa regex é considerado de escopo de usuário;
  • => my-company-*: qualquer pacote que case com essa regex é considerado de domínio da organização/empresa;
  • => **: todo e qualquer pacote que não seja capturado pelos escopos apresentados acima.

🔗 As propriedades de nível de acesso access, publish e unpublish são melhor explicadas aqui: https://verdaccio.org/docs/packages.

A propriedade proxy indica que caso o pacote não esteja presente no servidor do Verdaccio este deve ser buscado no registro informado em uplinks.npmjs, que no exemplo acima aponta para: https://registry.npmjs.org/.

Já em relação a packages.my-company-*, observe que somente o grupo root (o nome do usuário é também o nome do seu grupo) tem autorização para despublicar (unpublish) pacotes. Observe ainda que devido a ausência da propriedade proxy, caso o pacote buscado case com a regex my-company-* e ele não exista dentro do servidor, o mesmo não será buscado em outro local pois a propriedade proxy não dentro do seu escopo, ou seja, se o nome escolhido para este escopo for muito simples, você pode ter problemas, deste modo é valido considerar incluir a propriedade proxy para este escopo também.

Por fim packages.** tem somente permissão de acesso, ou seja, nossos usuários só poderão publicar pacotes que casem com os dois primeiros padrões, já que ** recebeu permissão de somente acesso.

💡Caso não tenha ficado claro, o padrão my-company-* pode ser adotado para representar pacotes da organização ou até mesmo pacotes criados para um cliente específico.

Subindo o Verdaccio via Docker

Execute a seguinte instrução na raiz do seu diretório de trabalho:

docker run \
--rm \
--name verdaccio \
--detach \
--publish 4873:4873 \
--volume $(pwd)/conf:/verdaccio/conf \
--volume $(pwd)/storage:/verdaccio/storage \
--volume $(pwd)/plugins:/verdaccio/plugins \
verdaccio/verdaccio

Acesse o seguinte endereço no seu navegador: http://localhost:4873.

Essa será a tela apresentada:

Operações básicas

Toda vez que precisar logar, deslogar, baixar, publicar ou despublicar um pacote você terá que informar o parâmetro --registry http://localhost:4873, com o tempo isso se torna um pouco repetitivo demais, porém, existem duas formas de contornar este "problema".

Solução 1 - Execute:

npm set registry http://localhost:4873/

Isso irá adicionar o seguinte valor registry=http://localhost:4873/ ao arquivo ~/.npmrc, ou seja, este registro será globalmente reconhecido pelo NPM.

Solução 2 - Crie um arquivo .npmrc na raiz do seu repositório de código e adicione o valor registry=http://localhost:4873 a ele, você pode até versionar este junto com o projeto, afinal de contas ele possui escopo local e afeta somente o projeto de mesmo nível e níveis inferiores!

Para cadastrar um usuário basta executar:

npm adduser --registry http://localhost:4873/

Lembre-se que caso esteja utilizando o .npmrc local ou global conforme apresentado anteriormente, você poderá omitir o parâmetro --registry http....

Ao executar a instrução acima você deverá preencher algumas informações que serão solicitadas pela CLI. Sendo elas: Username, Password e Email. Caso tudo corra bem a CLI irá apresentar a mensagem Logged in as fabio on http://localhost:4873/., ou seja, você está logado com o usuário que acabou de ser criado, neste exemplo criei o usuário fabio.

Caso você precise deslogar:

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

Já se precisar logar novamente:

npm login --registry http://localhost:4873/

Para alterar a senha do usuário atualmente logado:

npm profile set password --registry http://localhost:4873/

Publicando um pacote

Para exemplificar o processo de publicação de um pacote, nada mais justo do que criarmos e publicarmos um pacote em nosso Registro NPM. Sendo assim crie um diretório chamado hello-world, acesse este e inicialize o mesmo como um repositório NPM:

npm init -y

Edite o arquivo package.json e altere o valor hello-world para:

@fabio/hello-world

@fabio representa o escopo do usuário que eu criei no servidor, ou seja, estou falando que o pacote em questão é de propriedade deste usuário. Caso tenha criado um usuário com outro nome, faça os devidos ajustes.

Crie um arquivo README.md com o seguinte conteúdo:

# @fabio/hello-worldIsso é um README.md de exemplo.

Crie um arquivo index.js e adicione este conteúdo a ele:

module.exports = function () {
console.log('Hello, world!');
}

⚠️ Para executar os passos abaixo é necessário que você tenha criado um usuário e esteja logado, estes passos já foram ensinados em tópicos anteriores.

Execute essa instrução para publicar o pacote:

npm publish --registry http://localhost:4873/

Acesse o servidor em: http://localhost:4873 e visualize o seguinte resultado:

Ao clicar sobre o pacote temos está tela de resultado:

Baixando/instalado o pacote

Agora você poderia facilmente baixar e instalar o pacote executando essa instrução:

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

Posteriormente poderia simplesmente importar em seu código/projeto e sair usando. Ex:

const hello = require('@fabio/hello-world')hello()

Despublicar um pacote ou versão do Registro NPM

Para despublicar/remover uma versão especifica basta informar a mesma logo após o nome do pacote:

npm unpublish --registry http://localhost:4873/ @fabio/hello-world@1.0.0

Já para despublicar o pacote como um todo, basta executar:

npm unpublish --registry http://localhost:4873/ @fabio/hello-world -f

✌️Conclusão

O Verdaccio é um projeto que não apresenta de forma nativa recursos avançados de gestão de acesso, porém, por ser uma solução open-source e construída utilizando basicamente TypeScript, você tem uma liberdade muito grande para adicionar controles customizados ou até mesmo criar plugins para atender quaisquer outras necessidades que venham a surgir.

Recomendo ainda que acesse a documentação oficial em https://verdaccio.org/docs e veja o que a ferramenta tem a oferecer.

--

--

Fábio J L Ferreira

Arquiteto de software, palestrante e um profundo admirador a filosofia do software livre...