使用verdaccio搭建npm私有源

3,971 阅读2分钟

业务中,与合作方共建代码,有时需要提供npm私有包。使用代码copy的方法,影响整个项目的可移植性,也无法做版本控制和管理。在此背景下,选择使用verdaccio搭建一个轻型的npm私有源服务,为合作方提供需要共享的私有包。这里简要记录下搭建过程安全策略使用方法

描述说明 本文代称
原始源registry registry.x.com
原始源私有scope xscope
需要共享的模块 xscope|modulea
私有源域名 abc.com
私有源registry abc.com/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://registry.x.com 
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://abc.com/npm/

2、项目里增加preinstall脚本,合作方无感知的使用

利用npm preinstall的钩子,项目的package.json里增加preinstall要执行的脚本,这样合作方可以无感知的安装。

bash版

#!/bin/bash
registry=$(npm config get registry);
if ! [[ $registry =~ "http://registry.x.com" ]]; then
    npm config set @xscope:registry https://abc.com/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://abc.com/npm/');
    }
});

补充个小小:出于安全考虑,npm install在root用户下运行不能直接执行脚本,需要在install的时候,追加参数--unsafe-perm

本季完结撒花!新番希望可以讨论下verdaccio的存储管理和诟病多时的npm安全性!