Verdaccio 部署私有 NPM 包服务

Published on 12 June 2023
19 min read
Node
Npm
Verdaccio 部署私有 NPM 包服务

前言

市面上目前有很多种 npm 私有服务方案,这里列举一些方案以及他们的优缺点

  1. npm Enterprise:这是 npm 官方提供的企业级服务,它支持私有包和公共包,并提供了一些高级功能,如集成身份验证和内置审计功能。然而,这是一项付费服务,而且价格相对较高。
    1. 优点:来自 npm 官方,高级功能,集成身份验证和审计。
    2. 缺点:价格高,可能超出一些小型团队或个人开发者的预算。
  2. ArtifactoryJFrogArtifactory 是一款强大的仓库管理器,支持多种包管理系统,包括 npm。它提供了一些高级功能,如安全扫描和元数据跟踪。
    1. 优点:支持多种包管理系统,高级功能如安全扫描和元数据跟踪。
    2. 缺点:与 Verdaccio 相比,设置和管理可能更复杂。
  3. Sonatype Nexus RepositoryNexus 是另一款支持多种包管理系统的仓库管理器,它也支持 npm。它的界面直观易用,且支持 LDAPActive Directory 这类目录服务。
    1. 优点:支持多种包管理系统,直观的界面,支持目录服务。
    2. 缺点:可能不如 Verdaccio 那么简洁和轻量级。
  4. GitHub Packages:这是 GitHub 提供的包管理服务,支持 npm 和其他一些包管理系统。它可以与你的 GitHub 项目紧密集成,并支持在同一个组织中共享包。
    1. 优点:与 GitHub 项目紧密集成,支持在组织中共享包。
    2. 缺点:如果你的项目或团队并不使用 GitHub,那么这项服务可能就不那么有用了。
  5. GitLab
    1. 团队没有使用它作为代码仓库,相对于 Verdaccio 来说比较重

为什么使用 verdaccio:

  1. 自主管理:Verdaccio 允许团队拥有自己的私有 npm 存储库,对包的发布和版本控制有更大的自主权。这样可以减少对公共 npm 存储库的依赖,并提高安全性。
  2. 加速开发:由于 Verdaccio 将下载过的包缓存在本地,这将极大地提高了安装包的速度,特别是在网络不佳的情况下。
  3. 易于设置和使用:Verdaccio 的安装和配置过程相对简单,基本不需要过多的系统知识。一旦设置完成,开发者们可以直接使用 npm 命令来发布和安装包,无需学习新的工具。
  4. 节省成本:与一些商业的 npm 存储库管理服务相比,Verdaccio 是开源的,免费的。它可以帮助团队节省预算。
  5. 控制访问:通过 Verdaccio,你可以配置包的访问权限,比如你可以只允许特定用户或团队访问某个包,或者限制哪些用户可以发布包,这可以提高安全性并减少错误的可能。
  6. 持续集成友好:由于 Verdaccio 提供了本地的 npm 服务,这意味着你可以在没有互联网连接的情况下进行开发和测试。这对于持续集成/持续部署 (CI/CD) 环境特别有用。
  7. 生态系统兼容性:Verdaccio 与 npm 和 yarn 完全兼容,这意味着开发者们不需要改变他们现有的工作流程。
  8. 社区支持:Verdaccio 有一个活跃的开源社区,你可以从中获得帮助和支持。同时,由于其开源的特性,如果你遇到问题,你甚至可以参与到其开发和改进中去。

安装

首先在服务器上确保安装最新版本的 pnpm,全局安装verdaccio

typescript
pnpm add -g verdaccio

如果是第一次通过pnpm全局安装依赖,可能会提示 Run pnpm setup to create it automatically, or set the global-bin-dir setting, or the PNPM_HOME env variable. The global bin directory should be in the PATH.

这条信息建议运行”pnpm setup”命令来自动创建设置,或者设置”global-bin-dir”配置项,或者设置”PNPM_HOME”环境变量。全局 bin 目录应该在 PATH 环境变量中。

执行 pnpm setup

typescript
pnpm setup

输出

bash
# 表示在 `/root/.bashrc` 文件中添加了新行。`.bashrc` 文件是 Bash shell 的启动脚本文件,用于配置和初始化 Bash 环境
Appended new lines to /root/.bashrc

Next configuration changes were made:
# 将 `PNPM_HOME` 环境变量设置为 `/root/.local/share/pnpm`。这意味着 [[PNPM]] 将使用该目录作为全局包和其他文件的存储位置。
export PNPM_HOME="/root/.local/share/pnpm"
# 将 `PNPM_HOME` 目录添加到 PATH 环境变量中。PATH 环境变量定义了可执行文件的搜索路径,这样你可以在终端中直接运行 PNPM 命令,而无需指定完整的路径。
export PATH="$PNPM_HOME:$PATH"

To start using pnpm, run:
# 开始使用 PNPM,需要运行 "source /root/.bashrc" 命令。该命令将重新加载 ".bashrc" 文件
source /root/.bashrc

启动

执行source /root/.bashrc 后继续执行 pnpm add -g verdaccio,安装完成后执行 verdaccio命令,输入

bash
```sh # Verdaccio 的配置文件路径 info --- config file - /root/.config/verdaccio/config.yaml # 加密算法警告 info --- the "crypt" algorithm is deprecated consider switch to "bcrypt" in the configuration file. Read the documentation for additional details # Verdaccio 使用的 htpasswd 文件的路径,htpasswd 文件用来存储用户的身份验证凭据 info --- using htpasswd file: /root/.config/verdaccio/htpasswd # 下面两个表示 verdaccio 成功加载了 verdaccio-htpasswd 和 verdaccio-audit 插件 info --- plugin successfully loaded: verdaccio-htpasswd info --- plugin successfully loaded: verdaccio-audit # 启动的地址和当前的 verdaccio 版本 warn --- http address - http://localhost:4873/ - verdaccio/5.24.1 ```

执行 verdaccio 之后就可以在localhost:4873 中访问到了,localhost:4873 是默认配置的地址,可以通过 CLI 或者config.yaml文件来修改

CLI 启动参数

Command Line Tool | Verdaccio

如果想要修改默认的启动主机地址和端口,可以通过以下命令启动,监听所有可用的网络接口,并使用端口 4873

bash
verdaccio --listen 0.0.0.0:4873 --config ./config.yaml

这种启动方式是临时的,如果想要永久修改,则需要修改config.yaml 配置文件,路径为 /root/.config/verdaccio,找到其中的 listen配置项

bash
listen:
  # - localhost:4873            # default value
  # - http://localhost:4873     # same thing
  - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
# - https://example.org:4873  # if you want to use https
# - "[::1]:4873"                # ipv6
# - unix:/tmp/verdaccio.sock    # unix socket

修改后再使用verdaccio 命令启动后就是0.0.0.0:4873主机和端口

PM2 启动

使用 PM2 来启动服务,方便进程管理、监控守护和自动重启等,首先确保已安装 PM2 - Home

bash
npm install pm2 -g | pnpm install -g pm2

执行 pm2 start verdaccio 或者 pm2 start which verdaccio 来启动 使用 verdaccio 搭建 npm 私有库 pm2 守护进程_npm 守护进程_青鱼梦镜白的博客-CSDN 博客

pm2 启动有点问题,一直报错,怀疑是跟 Node 版本有关系,当期 Node 版本是 16.4,想要升级最新版,但是服务器是 Centos7,缺少 Node 18 所必须的依赖,想升级 18 还需要升级 Ctntos 为 18,所以使用 Docker 把

使用 Docker

确保已安装 [[Docker]],拉取 docker 镜像

bash
docker pull verdaccio/verdaccio

创建 docker/verdaccio 目录并新建 config.yaml 文件,文件内容可以从这里复制verdaccio/docker.yaml at master · verdaccio/verdaccio · GitHub 创建

  1. conf/config.yaml 文件夹及文件
  2. htpasswd文件
  3. storage文件夹
  4. plugins 文件夹
注意,`htpasswd` 是文件,不是文件夹,不要新建错了
bash
/root/docker/verdaccio/config.yaml
/root/docker/verdaccio/storage
/root/docker/verdaccio/plugins
/root/docker/verdaccio/htpasswd

[!WARING] 注意,如果没有目录权限的话需要先获取权限 chown -R 10001:65533 /home/verdaccio/storage

修改config.yaml文件:

yaml
# 存放软件所有软件包的目录
storage: /verdaccio/storage
# 存放所有插件的目录
plugins: /verdaccio/plugins
# 存放用户信息设置
auth:
	htpasswd:
		file: /verdaccio/htpasswd

命令启动

修改保存后执行以下命令

bash
V_PATH=/root/docker/verdaccio; docker run -d -it --name verdaccio 
	-p 4873:4873 
	-v $V_PATH/conf/config.yaml:/verdaccio/conf/config.yaml 
	-v $V_PATH/storage:/verdaccio/storage 
	-v $V_PATH/htpasswd:/verdaccio/htpasswd 
	-v $V_PATH/plugins:/verdaccio/plugins 
	verdaccio/verdaccio
  1. V_PATH=/home/verdaccio:这个就是给后面 $V_PATH 使用的
  2. docker run -d -it --name verdaccio
    1. -d  守护进程 之前可能是使用 PM2 来管理;
    2. -it  是 -i 与 -t 的缩写;
    3. -i:  以交互模式运行容器,通常与 -t 同时使用;
    4. -t:  为容器重新分配一个伪输入终端,通常与 -i 同时使用
    5. --name verdaccio:  为容器指定一个名称;
    6. \换行
    7. -p:  指定端口映射,格式为:主机 (宿主) 端口:容器端口。当然还有-P 随机端口映射,容器内部端口随机映射到主机的端口
    8. --volume , -v:  绑定一个卷 : /verdaccio/conf —> /home/verdaccio/conf 等等

启动成功后访问 ip:4873就可以看到服务启动成功了

docker-compose 启动

如果不想用命令行的方式启动,可以通过 docker-compose 来启动,首先在verdaccio目录下创建docker-compose.yaml文件,内容如下

yaml
version: '3'
services:
  verdaccio:
    image: verdaccio/verdaccio
    container_name: 'verdaccio'
    networks:
      - node-network
    environment:
      - VERDACCIO_PORT=4873
    ports:
      - 4873:4873
    volumes:
      - /root/docker/verdaccio/conf:/verdaccio/conf
      - /root/docker/verdaccio/storage:/verdaccio/storage
      - /root/docker/verdaccio/htpasswd:/verdaccio/htpasswd
      - /root/docker/verdaccio/plugins:/verdaccio/plugins
networks:
  node-network:
    driver: bridge

然后在当前目录下执行

bash
docker-compose up -d

这里我执行完成之后显示正在启动,然后 done 掉了,容器没有启动成功,通过 docker ps -a 查看所有的容器发现verdaccio容器状态为失败

查看日志docker logs verdaccio

json
verdaccio    | info --- config file  - /verdaccio/conf/config.yaml
verdaccio    | fatal--- uncaught exception, please report this
verdaccio    | Error: EACCES: permission denied, access '/root/docker/verdaccio/storage/data/.sinopia-db.json'
verdaccio    |     at Object.accessSync (node:fs:260:3)
verdaccio    |     at LocalDatabase._buildStoragePath (/usr/local/lib/node_modules/verdaccio/node_modules/@verdaccio/local-storage/lib/local-database.js:248:19)
verdaccio    |     at new LocalDatabase (/usr/local/lib/node_modules/verdaccio/node_modules/@verdaccio/local-storage/lib/local-database.js:27:22)
verdaccio    |     at LocalStorage._loadStorage (/usr/local/lib/node_modules/verdaccio/build/lib/local-storage.js:734:14)
verdaccio    |     at new LocalStorage (/usr/local/lib/node_modules/verdaccio/build/lib/local-storage.js:33:31)
verdaccio    |     at Storage.init (/usr/local/lib/node_modules/verdaccio/build/lib/storage.js:43:25)
verdaccio    |     at _default (/usr/local/lib/node_modules/verdaccio/build/api/index.js:121:17)
verdaccio    |     at startVerdaccio (/usr/local/lib/node_modules/verdaccio/build/lib/bootstrap.js:50:22)
verdaccio    |     at InitCommand.execute (/usr/local/lib/node_modules/verdaccio/build/lib/cli/commands/init.js:63:37)
verdaccio    |     at InitCommand.validateAndExecute (/usr/local/lib/node_modules/verdaccio/node_modules/clipanion/lib/advanced/Command.js:73:37)

显式因为权限问题报错了,搞了好久没搞好,本身我的 docker 也不会多少,找朋友问了下,朋友一眼就看出问题了,是因为我的 config.yaml 文件中的配置路径写错了,在 config.yaml 文件中,storage 路径应该是相对于容器内的路径,而不是宿主机的绝对路径。

text
# 错误路径
storage: /root/docker/verdaccio/storage
plugins: /root/docker/verdaccio/plugins
auth:
	htpasswd:
		file: /root/docker/verdaccio/htpasswd

# 正确路径
storage: /verdaccio/storage
plugins: /verdaccio/plugins
auth:
	htpasswd:
		file: /verdaccio/htpasswd

修改完路径后再次执行 docker-compose up -d 就能正确启动服务了。

另外注意一点,我这里所有的东西都是在 root 目录下操作的,因为是自己的服务器随表搞的,稳妥的做法是将应用程序放在 /opt 目录下,数据放在 /var 目录下。例如可以将 Verdaccio 相关的文件放在 /opt/verdaccio 目录下,配置文件、存储数据等放在 /var/verdaccio 目录下。这样能够保证安全性

配置文件一览

yaml
# 存储所有的包文件路径,这里设置为 /verdaccio/storage。
storage: /verdaccio/storage
# 插件目录,可在该目录中存放一些 Verdaccio 的扩展插件。
plugins: /verdaccio/plugins

# https://verdaccio.org/docs/webui
# 与 Verdaccio 的网页界面有关的设置。
web:
  title: Abiao
# 身份验证配置
auth:
  htpasswd:
    file: /verdaccio/htpasswd
    # 0 -1
    max_users: 1000

# uplinks 配置,用于定义其他已知的仓库
uplinks:
  # 将请求代理到官方的 npmjs 仓库。
  npmjs:
    url: https://registry.npmjs.org/

# 包配置
# https://verdaccio.org/docs/protect-your-dependencies/
# https://verdaccio.org/docs/configuration#packages
packages:
  '@*/*':
    # scoped packages
    access: $all
    publish: $authenticated
    unpublish: $authenticated
    proxy: npmjs
  # 允许所有用户读取 scoped 包,但只有已验证的用户才能发布和取消发布 scoped 包。
  # 请求会通过 npmjs uplink 代理到官方的 npmjs 仓库。
  '**':
    # 通配符配置,适用于其他所有包
    access: $all

    # Allow all known users to publish/publish packages
    # (anyone can register by default, remember?)
    publish: $authenticated
    unpublish: $authenticated

    # # 允许所有用户读取和发布其他包,请求会通过 npmjs uplink 代理到官方的 npmjs 仓库。
    proxy: npmjs

server:
  # 设置 HTTP 连接的 keep-alive 超时时间为 60 秒。
  keepAliveTimeout: 60
# https://verdaccio.org/docs/configuration#listen-port
listen:
  - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)

middlewares:
  audit:
    enabled: true

# log settings
log: { type: stdout, format: pretty, level: http }
# Translate your registry, api i18n not available yet
i18n:
  # list of the available translations https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md
  web: en-US

NPM 配置

初始化

初始化 verdaccio时需要设置用户名密码等,然后就可以直接发包了

bash
pnpm adduser --registry http://IP:4873/

依次输入usernamepasswordemail 就创建成功了,创建成功之后可以在 verdaccio/htpasswd文件中查看到相关的用户信息。

注意,如果本地 `npm` 版本为 `npm9` 可能会遇到错误 `Web login not supported` 这时候需要在命令后面加上 `--auth-type=legacy`
bash
pnpm adduser --registry http://IP:4873/ --auth-type=legacy

参考:

文件错误问题

22522f6b04f2e086170ca06b674fe8e.png 一开始执行 npm adduser 之后就挂起了,然后去看了下 docker日志发现上面的错误,一开始以为是权限问题,各种修改权限,查资料都没解决,最后发现是因为 htpasswd 文件被我创建成了文件夹。

权限问题

bash
Error: EACCES: permission denied, open '/verdaccio/htpasswd'
http <-- 500, user: null(117.147.119.178), req: 'PUT /-/user/org.couchdb.user:liyang', error: internal server error
info <-- 117.147.119.178 requested 'PUT /-/user/org.couchdb.user:liyang'
http <-- 200, user: null(117.147.119.178), req: 'PUT /-/user/org.couchdb.user:liyang', bytes: 157/0
error--- the user liyang could not being added. Error: EACCES: permission denied, open '/verdaccio/htpasswd'
error--- unexpected error: EACCES: permission denied, open '/verdaccio/htpasswd'

npm 版本问题

bash
pnpm adduser --registry --auth-type=legacy http://xxxx:4873/
npm WARN invalid config registry="--auth-type=legacy" set in command line options
npm WARN invalid config Must be full url with "http://"
npm notice Log in on http://42.194.136.132:4873/
npm ERR! code ENYI
npm ERR! Web login not supported

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/liyang/.npm/_logs/2023-05-25T15_02_16_668Z-debug-0.log

npm 9 版本会在登录的时候报错 Web login not supported。可通过上面的方案解决,

发布包

  1. 首先需要登录
pnpm login --registry http://IP:4873/

or

pnpm login --registry http://IP:4873/ --auth-type=legacy
  1. 进入项目中发布
npm publish

刷新网站查看 没问题的话就可以看到刚刚上传的包了。