NPM 私服搭建完整指南
一、为什么需要搭建 NPM 私服
在企业应用开发中,搭建私有 NPM 仓库是必要的基础设施选择:
核心价值
代码私密性保障:企业内部业务组件、工具库等敏感代码需要私有化管理,避免泄露
访问速度优化:局域网内部访问,依赖下载速度显著提升,特别适合大型项目和 CI/CD 场景
权限精细控制:可针对不同团队、项目设置发布、访问权限,便于维护和管理
成本效益显著:npm 官方私有包需要付费订阅,自建私服无额外成本
适用场景
企业内部组件库、工具库共享
多项目公共模块统一管理
特定版本依赖的稳定存储
CI/CD 流程中的依赖缓存
二、主流私服方案对比
方案 优势 劣势 适用场景
Verdaccio 轻量级、零配置启动、专注 npm、配置简单 功能相对单一、企业级特性较少 中小型团队、纯前端团队、快速部署
Nexus 多格式支持(npm/Maven/Docker)、企业级权限管理、功能强大 相对重量级、配置复杂、需要 Java 环境 大型企业、多语言团队、已有 Nexus 基础设施
cnpm 国内访问快、支持大规模镜像、企业级功能强 部署复杂、需要数据库、维护成本高 超大规模团队、对国内访问速度要求极高
Artifactory 功能最全面、支持所有主流包管理器、企业级特性丰富 商业软件、价格昂贵、学习曲线陡峭 大型企业、预算充足、需要统一管理所有包管理器
推荐选型策略:
90% 的中小型团队 → Verdaccio
大型企业 / 多技术栈团队 → Nexus
超大规模团队(阿里级别)→ cnpm
三、Verdaccio 深度实践
3.1 Verdaccio 核心特性
Verdaccio 是基于 Node.js 的轻量级私有 npm 代理注册表,具有以下特点:
轻量级设计:采用 Node.js 编写,无外部数据库依赖,数据存储于本地文件系统
简单配置:单个 YAML 配置文件即可完成权限、上游代理、缓存等设置
缓存和代理:可作为上游 npm 注册表的代理,自动缓存已下载的包
灵活访问控制:支持基于用户和包的访问权限管理
插件生态:支持身份验证、审计日志等插件扩展
3.2 安装方式对比
方式一:全局安装(适合快速体验)
bash
全局安装
npm install -g verdaccio
查看基本信息
verdaccio -h
启动服务
verdaccio
注意:Verdaccio 6.x 要求 Node.js 18+,推荐使用 Node.js 20 LTS
方式二:Docker 部署(推荐用于生产环境)
基础部署命令:
bash
拉取镜像
docker pull verdaccio/verdaccio:6.x
运行容器(数据持久化)
docker run -d --name verdaccio
-p 4873:4873
-v /data/verdaccio/conf:/verdaccio/conf
-v /data/verdaccio/storage:/verdaccio/storage
-v /data/verdaccio/plugins:/verdaccio/plugins
verdaccio/verdaccio:6.x
Docker Compose 部署(推荐) :
yaml
version: '3.8'
services:
verdaccio:
image: verdaccio/verdaccio:6.x
container_name: verdaccio-prod
restart: unless-stopped
ports:
- "4873:4873"
environment:
-
VERDACCIO_PORT=4873
-
VERDACCIO_PROTOCOL=http
HTTPS 配置时使用
- VERDACCIO_PUBLIC_URL=https://registry.example.com
volumes:
-
./storage:/verdaccio/storage
-
./config:/verdaccio/conf
-
./plugins:/verdaccio/plugins
networks:
- verdaccio-net
networks:
verdaccio-net:
driver: bridge
权限设置关键点:
bash
Docker 容器内默认使用 uid 10001 运行
sudo chown -R 10001:65533 /data/verdaccio
方式三:使用 PM2 守护进程
bash
安装 PM2
npm install -g pm2 --unsafe-perm
启动 Verdaccio
pm2 start verdaccio --name "private-npm" -- --config /opt/verdaccio/conf/config.yaml
查看状态
pm2 list
查看日志
pm2 logs verdaccio
3.3 核心配置详解
配置文件结构
yaml
存储路径
storage: /verdaccio/storage
插件目录
plugins: /verdaccio/plugins
Web UI 配置
web:
enable: true
title: 企业私有 NPM 仓库
gravatar: true
darkMode: false
身份认证设置
auth:
htpasswd:
file: /verdaccio/conf/htpasswd
max_users: 1000 # -1 表示禁止新用户注册
上游代理配置
uplinks:
npmjs:
url: https://registry.npmjs.org/
timeout: 30s
taobao:
url: https://registry.npmmirror.com/
timeout: 10s
包访问权限控制(核心)
packages:
'@your-scope/*':
access: $authenticated # 只有认证用户可访问
publish: $authenticated # 只有认证用户可发布
unpublish: $authenticated # 只有认证用户可取消发布
proxy: npmjs # 私有包不需要代理
' **':
access: $all # 所有人可访问
publish: $authenticated
unpublish: $authenticated
proxy: npmjs taobao # 本地没有时,按顺序从上游拉取
服务器配置
server:
keepAliveTimeout: 60
日志配置
log:
type: stdout
format: pretty
level: http
监听配置(生产环境注意)
listen:
- 0.0.0.0:4873 # 允许外网访问,默认是 localhost:4873
配置字段详细说明
字段 说明 可选值
storage 包存储路径 文件系统路径
plugins 插件目录路径 文件系统路径
auth.htpasswd.file 用户密码文件路径 文件路径
auth.htpasswd.max_users 最大用户数 正整数 / -1(禁止注册)
uplinks 上游代理配置 多个上游地址
packages.*.access 访问权限 all / authenticated / anonymous / 具体用户名 packages.* .publish 发布权限 authenticated / 具体用户名
packages.*.proxy 代理上游 uplinks 中定义的名称
listen 监听地址 localhost:4873 / 0.0.0.0:4873
3.4 HTTPS 和反向代理配置
方式一:直接配置 HTTPS
yaml
config.yaml
listen:
https:
key: /path/to/verdaccio-key.pem
cert: /path/to/verdaccio-cert.pem
ca: /path/to/verdaccio-csr.pem
public_url: https://registry.example.com:4873/
**证书生成 **:
bash
openssl genrsa -out verdaccio-key.pem 2048
openssl req -new -sha256 -key verdaccio-key.pem -out verdaccio-csr.pem
openssl x509 -req -in verdaccio-csr.pem -signkey verdaccio-key.pem -out verdaccio-cert.pem
方式二:Nginx 反向代理(推荐)
nginx
HTTP 配置
server {
listen 80;
server_name registry.example.com;
location / {
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;
proxy_pass http://127.0.0.1:4873/;
proxy_redirect off;
}
}
HTTPS 配置
server {
listen 443 ssl http2;
server_name registry.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
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;
proxy_pass http://127.0.0.1:4873/;
proxy_read_timeout 600;
proxy_redirect off;
}
}
**Docker 部署时的环境变量 **:
bash
docker run -d
-e VERDACCIO_PUBLIC_URL='https://registry.example.com'
-p 4873:4873
verdaccio/verdaccio:6.x
3.5 客户端配置与使用
用户注册和登录
bash
注册用户(私服端需要启用注册功能)
npm adduser --registry http://localhost:4873
查看当前登录用户
npm whoami --registry http://localhost:4873
登出
npm logout --registry http://localhost:4873
发布私有包
步骤一:初始化项目
bash
创建项目目录
mkdir my-private-package
cd my-private-package
初始化 package.json
npm init -y
步骤二:修改 package.json
json
{
"name": "@your-scope/my-private-package",
"version": "1.0.0",
"private": false,
"description": "私有包示例",
"main": "index.js"
}
步骤三:发布
bash
登录(如果未登录)
npm login --registry http://localhost:4873
发布
npm publish --registry http://localhost:4873
安装私有包
bash
方式一:临时指定源
npm install @your-scope/my-private-package --registry http://localhost:4873
方式二:配置作用域(推荐)
npm config set @your-scope:registry http://localhost:4873
npm install @your-scope/my-private-package
3.6 使用 NRM 管理镜像源
安装 NRM
bash
全局安装
npm install -g nrm
解决 open 包兼容性问题(Node 16+)
npm install -g nrm open@8.4.2
NRM 常用命令
bash
查看所有镜像源
nrm ls
切换镜像
nrm use taobao
添加自定义镜像
nrm add company-npm http://npm.company.com:4873
删除镜像
nrm del company-npm
测试镜像速度
nrm test taobao
添加私服到 NRM
bash
添加 Verdaccio 私服
nrm add verdaccio http://localhost:4873
切换到私服
nrm use verdaccio
验证
nrm ls
四、Nexus 企业级方案
4.1 Nexus 核心概念
Nexus 支持三种仓库类型:
仓库类型 用途 配置要点
Hosted(托管) 存储私有包 Deployment policy 设为 Allow redeploy
Proxy(代理) 代理远程仓库 Remote storage 填写上游地址
Group(组) 聚合多个仓库 添加 Hosted 和 Proxy 到 Members
4.2 Nexus 配置流程
步骤一:创建 Blob 存储
plaintext
设置 → Blob Stores → Create blob store
名称:npm-blob
类型:File
步骤二:创建 Hosted 仓库
plaintext
设置 → Repository → Repositories → Create repository
选择:npm (hosted)
名称:npm-private
Blob store:npm-blob
Deployment policy:Allow redeploy(允许覆盖发布)
步骤三:创建 Proxy 仓库
plaintext
设置 → Repository → Repositories → Create repository
选择:npm (proxy)
名称:npm-proxy
Remote storage:https://registry.npmmirror.com/
Blob store:npm-blob
步骤四:创建 Group 仓库
plaintext
设置 → Repository → Repositories → Create repository
选择:npm (group)
名称:npm-group
Blob store:npm-blob
Members:
- npm-private
- npm-proxy
4.3 Nexus 客户端配置
bash
配置为组仓库地址
npm config set registry http://nexus.example.com:8081/repository/npm-group/
登录
npm login --registry=http://nexus.example.com:8081/repository/npm-private/
发布到私有仓库
npm publish --registry=http://nexus.example.com:8081/repository/npm-private/
五、作用域包(Scoped Packages)深度解析
5.1 作用域包的概念
作用域包是 npm 提供的命名空间机制,格式为 @scope/package-name:
**解决命名冲突 **:包名只需在作用域内唯一
**清晰的归属关系 **:@babel/core 明确属于 babel 组织
**支持私有化 **:天然适合企业私有包管理
5.2 作用域包的配置方式
方式一:通过 .npmrc 配置(推荐)
在项目根目录创建 .npmrc 文件:
ini
作用域路由:@your-scope 开头的包走私有仓库
@your-scope:registry=https://nexus.example.com/repository/npm-private/
认证信息
//nexus.example.com/repository/npm-private/:_authToken=your-token-here
强制认证
//nexus.example.com/repository/npm-private/:always-auth=true
其他包走公共源
registry=https://registry.npmjs.org
方式二:命令行配置
bash
设置作用域对应的 registry
npm config set @your-scope:registry http://localhost:4873
验证配置
npm config get @your-scope:registry
5.3 发布作用域包
发布到公共仓库
bash
初始化时指定作用域
npm init --scope=@your-org
首次发布必须指定访问权限
npm publish --access public
发布到私有仓库
bash
package.json
{
"name": "@your-org/private-package"
}
发布(私有包默认为 restricted)
npm publish --registry http://localhost:4873
5.4 .npmrc 配置优先级
级别 位置 优先级 说明
项目级 项目根目录/.npmrc 最高 推荐用于项目特定配置
用户级 ~/.npmrc 中 影响当前用户所有项目
全局级 npm config -g 低 影响系统所有用户
默认级 npm 内置 最低 公共仓库 https://registry.npmjs.org
**配置合并规则 **:优先级高的配置会覆盖优先级低的配置。
六、生产环境最佳实践
6.1 安全配置建议
Verdaccio 安全配置
yaml
禁用公开注册
auth:
htpasswd:
max_users: -1 # -1 表示禁止新用户注册
私有包移除代理(避免依赖混淆攻击)
packages:
'@your-scope/*':
access: $authenticated
publish: $authenticated
unpublish: $authenticated
移除 proxy: npmjs
限制上传包大小
server:
max_body_size: 10mb
启用审计日志
middlewares:
audit:
enabled: true
Nexus 安全配置
plaintext
Security → Anonymous Access:关闭匿名访问
Security → Realms:添加 npm Bearer Token Realm
Security → Roles:创建细粒度权限角色
6.2 备份与恢复
Verdaccio 备份
bash
备份存储目录
tar -czf verdaccio-backup-$(date +%Y%m%d).tar.gz /data/verdaccio/storage
备份配置文件
tar -czf verdaccio-config-backup-$(date +%Y%m%d).tar.gz /data/verdaccio/conf
Nexus 备份
bash
备份 nexus-data 目录
tar -czf nexus-backup-$(date +%Y%m%d).tar.gz /path/to/nexus-data
6.3 高可用部署
使用 Docker Swarm
yaml
version: '3.8'
services:
verdaccio:
image: verdaccio/verdaccio:6.x
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
ports:
- "4873:4873"
volumes:
-
verdaccio-storage:/verdaccio/storage
-
./config:/verdaccio/conf
networks:
- verdaccio-net
volumes:
verdaccio-storage:
driver: local
networks:
verdaccio-net:
driver: overlay
使用 Kubernetes + Helm
bash
添加 Helm 仓库
helm repo add verdaccio https://charts.verdaccio.org
helm repo update
部署
helm install npm-registry verdaccio/verdaccio
--namespace npm
--create-namespace
-f production-values.yaml
6.4 CI/CD 集成
GitHub Actions 示例
yaml
name: Publish to Private NPM
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
-
uses: actions/checkout@v3
- name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '20' - name: Configure .npmrc run: | echo "@your-scope:registry=${{ secrets.NPM_REGISTRY }}" >> ~/.npmrc echo "//${{ secrets.NPM_REGISTRY }}/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc echo "//${{ secrets.NPM_REGISTRY }}/:always-auth=true" >> ~/.npmrc - name: Publish run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
七、常见问题排查
7.1 Verdaccio 常见问题
问题 原因 解决方案
无法从外网访问 listen 配置为 localhost 改为 0.0.0.0:4873
发布 401 错误 未登录或权限不足 执行 npm login 重新登录
npm ERR! code E401 认证失败 检查 .npmrc 中的 Token 是否正确
安装包时卡住 上游代理配置错误 检查 uplinks 配置或更换上游源
PM2 启动失败 路径问题 使用 pm2 start \which verdaccio``
7.2 Nexus 常见问题
问题 原因 解决方案
401 Unauthorized Realms 未配置 添加 npm Bearer Token Realm
发布 400 错误 Hosted 仓库未允许 redeploy 修改 Deployment policy 为 Allow redeploy
找不到包 Group 仓库配置错误 检查 Members 列表是否包含所有仓库
Token 失效 Token 过期 重新登录获取新 Token
7.3 NPM 客户端常见问题
.npmrc 配置问题
**问题 1 **:401 认证失败
**排查步骤 **:
bash
检查当前 registry
npm config get registry
检查作用域配置
npm config get @your-scope:registry
验证 token
npm config get //registry.example.com/:_authToken
**问题 2 **:包发布到了错误的位置
**原因 **:作用域配置缺失
**解决 **:
bash
在 .npmrc 中显式配置
@your-scope:registry=https://your-private-registry.com/
八、性能优化建议
8.1 Verdaccio 优化
yaml
日志级别优化(生产环境)
log:
type: file
path: ./logs/verdaccio.log
format: pretty
level: warn
上游超时优化
uplinks:
npmjs:
url: https://registry.npmjs.org/
timeout: 60s
maxage: 30d # 缓存有效期
连接保持优化
server:
keepAliveTimeout: 60
8.2 Nexus 优化
plaintext
设置 → Repository → Cleanup Policies
- 启用自动清理策略
- 基于时间清理:保留最近 30 天
- 基于版本数清理:每个包保留最近 10 个版本
九、技术演进路线
9.1 Sinopia → Verdaccio
**Sinopia **:早期流行的私服工具,2015 年停止维护
**Verdaccio **:Sinopia 的分支项目,持续更新维护
**兼容性 **:Verdaccio 5.x 仍支持 Sinopia 插件,6.x 已移除支持
9.2 版本选择建议
Verdaccio 版本 Node.js 版本 推荐场景
4.x Node 14 遗留系统维护
5.x Node 16-18 稳定生产环境
6.x Node 18-20 LTS 新项目推荐
十、总结与建议
快速决策树
plaintext
你的团队规模?
├─ 小型团队(< 10 人)
│ └─ Verdaccio + Docker Compose
├─ 中型团队(10-50 人)
│ └─ Verdaccio + Docker Swarm / Kubernetes
└─ 大型团队(> 50 人)
└─ Nexus(如果已有)或 Verdaccio(纯前端)
推荐配置模板
**小型团队 Verdaccio 配置 **:
yaml
storage: ./storage
plugins: ./plugins
web:
title: 私有 NPM 仓库
auth:
htpasswd:
file: ./htpasswd
max_users: 10
uplinks:
npmjs:
url: https://registry.npmmirror.com/
packages:
'@company/*':
access: $authenticated
publish: $authenticated
proxy: npmjs
'** ':
access: $all
publish: $authenticated
proxy: npmjs
server:
keepAliveTimeout: 60
listen:
- 0.0.0.0:4873
log:
type: stdout
format: pretty
level: http
下一步行动
评估需求:根据团队规模和现有基础设施选择方案
快速验证:使用 Docker 快速部署 Verdaccio 验证可行性
渐进式迁移:从公共包代理开始,逐步引入私有包
建立规范:制定包命名规范、发布流程、权限管理策略
监控与优化:建立监控体系,持续优化性能和稳定性
附录:参考资料
Verdaccio 官方文档
Nexus 官方文档
npm 作用域包文档
NRM GitHub 仓库