业务中,与合作方共建代码,有时需要提供npm私有包。使用代码copy的方法,影响整个项目的可移植性,也无法做版本控制和管理。在此背景下,选择使用verdaccio搭建一个轻型的npm私有源服务,为合作方提供需要共享的私有包。这里简要记录下搭建过程、安全策略、使用方法。
描述说明 | 本文代称 |
原始源registry | |
原始源私有scope | xscope |
需要共享的模块 | xscope|modulea |
私有源域名 | |
私有源registry | /npm/ |
搭建过程
先过一遍verdaccio的官方文档,食用更佳!听这个名字,浓浓的拉美风情。没错,是几个意大利籍的巴西程序员,基于Sinopia开发的轻量级npm代理源。
1、安装verdaccio
$ npm install -g verdaccio
2、配置verdaccio
一般是这个文件:~/.config/verdaccio/config.yaml
2.1、verdaccio内部使用了express,服务启用在了uri根路径,这样比较浪费资源。增加配置:
url_prefix: /npm/
2.2、指定需要共享的npm包的uplinks,需要一个就加一个,这样做到共享范围的控制。(scope的形式无法做到清晰可控,不安全不要用!)
# a list of other known repositories we can talk to
uplinks:
npmjs:
url: https://registry.npmjs.org/
xnpmjs:
url: http://
packages:
'@xscope/modulea':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: xnpmjs
3、使用pm2启动verdaccio服务
利用pm2启动守护进程:
$ pm2 start verdaccio
通过pm2 show verdaccio
可以查看到out和error的log信息。
4、使用nginx做反向代理
不直接向外提供verdaccio服务,通过的nginx转发访问,官方文档有遗漏,我查了错误日志和源码才定位到!另外后来升级为https服务,官方配置更不够用(我的血汗泪,我最后的舞,全拿去吧QAQ),使用下面的配置
location ~ ^/npm/(.*)$ {
proxy_pass http://127.0.0.1:4873/$1;
# proxy_set_header Host $host:$server_port;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
# proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto https;
}
location ~ ^/-/(.*)$ {
proxy_pass http://127.0.0.1:4873/-/$1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
安全策略
外网可以访问到,加好安全策略!
1、强制https 域名备好证书,并将80访问重定向到443。
2、ip访问白名单限制 给内网、合作方的ip提供服务,其他forbidden!虽然也无法阻止代理中转和伪造,这应该够了。根据开发所处的环境,到达自己这层的请求可能几经nginx转发,要找下真实的源ip,确认下是在http头的哪个字段里,合理增加nginx的配置。我所在的开发网,实际的ip写在http头X-Real-IP中,同时还写入了X-Forwarded-For。所以nginx配置需要增加:
set_real_ip_from x.y.z;
real_ip_header X-Real-IP;
allow xxx; # 合作方ip
allow yyy; # 合作方ip
deny all;
3、只对需要共享的包设置uplink 参见2.2
使用方法
确保使用方在IP白名单内
1、单个私有包的安装
npm install @xscope/modulea --registry=https:///npm/
2、项目里增加preinstall脚本,合作方无感知的使用
利用npm preinstall的钩子,项目的package.json里增加preinstall要执行的脚本,这样合作方可以无感知的安装。
bash版
#!/bin/bash
registry=$(npm config get registry);
if ! [[ $registry =~ "http://" ]]; then
npm config set @xscope:registry https:///npm/
fi
node版
#!/usr/bin/env node
const { exec } = require('child_process');
exec('npm config get registry', function(error, stdout, stderr) {
if (!stdout.toString().match(/registry\.x\.com/)) {
exec(' npm config set @xscope:registry https:///npm/');
}
});
补充个小小:出于安全考虑,npm install在root用户下运行不能直接执行脚本,需要在install的时候,追加参数--unsafe-perm
。
本季完结撒花!新番希望可以讨论下verdaccio的存储管理和诟病多时的npm安全性!