New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用Sinopia搭建私有的npm仓库 #1

Open
Pines-Cheng opened this Issue Nov 26, 2016 · 1 comment

Comments

Projects
None yet
2 participants
@Pines-Cheng
Owner

Pines-Cheng commented Nov 26, 2016

需求

公司出于自身隐私保护需要,不想把自己的代码开源到包管理区,但是又急需一套完整包管工具,来管理越来越多的组件、模块和项目。对于前端,最熟悉的莫过于npm,bower等;但是bower的市场兼容性明显没有npm强壮,加之commonjs规范的日益成熟。npm应该是前端包管理的不二选择。

公司对于搭建本地私有npm库有如下要求:

  1. 私有包托管在内部服务器中
  2. 项目中使用了公共仓库上的公共包,也使用了内部服务器上的私有包
  3. 希望下载的时候,公共包走公共仓库,私有包走内部服务器的私有仓库
  4. 服务器硬盘有限,希望只缓存下载过的包,而不是全部同步。
  5. 对于下载,发布npm包有对应的权限管理,安装方便,配置简单,依赖少。

关于sinopia?

Sinopia 是一个零配置的私有的带缓存功能的npm包管理工具,作者是是rlidwka,一个大神,也是一只猫~ 往社区内贡献过很多代码,包括 jshttp, markdown-it 等等,也是 Node.js 核心代码库的活跃贡献者。

使用sinopia,你不用安装CouchDB或MYSQL之类的数据库,Sinopia有自己的迷你数据库,如果要下载的包不存在,它将自动去你配置的npm地址上去下载,而且硬盘中只缓存你现在过的包,以节省空间。

为什么选择sinopia

sinopia有以下几个优势值得关注:

  1. 不同步拉取npm库,占据大量硬盘,没有硬盘被撑爆的问题;
  2. 安装配置极其简单,不需要数据库;
  3. 支持配置上游registry配置,一次拉取即缓存;
  4. 支持forever及pm2守护进程管理;

其他方法

  • 使用 git+ssh 这种方式直接引用到 GitHub 项目地址

嗯,这种方式可行,也最简单,但真真的太烂了,姑且不说不能使用 semver,关键还是 url 太丑,如果是强迫症真的没法忍~

  • 使用cnpm

暂且不论 cnpm 只是作为镜像使用,其实这个方案缺点就挺多的,用的人多,速度不一定快,缓存,关键是不支持发布包以及登陆、注册,再加上配置过于复杂。而且,还需要安装数据库。

  • npm on-site

土豪啊,我还能说什么呢。。。但是问题是,npm在国内访问慢,还是不是的无法访问,花钱也买不到好的服务,何必呢。

部署

安装

首先,你要自己配置nodejs及npm的环境,然后运行

npm install -g sinopia

启动

$ sinopia
 warn  --- config file  - .....\AppData\Roaming\sinopia\config.yaml
 warn  --- http address - http://localhost:4873/

然后打开:http://localhost:4873/
image

如果能正常显示,说明安装成功。

使用pm2启动

当然,你也可以使用pm2或其他的守护进程进行管理,具体步骤如下:

安装pm2:npm install -g pm2

启动:pm2 start `which sinopia`

更多高级的pm2使用方法可以查看pm2电子书,相当详细,强烈推荐。

服务端配置

Sinopia的特点是,你在哪个目录运行,它的就会在对应的目录下创建自己的文件。目录下默认有两个文件:config.yamlstorage htpasswd 是添加用户之后自动创建的。

root@debian:/usr/local/apps/sinopia# ls
config.yaml  htpasswd  storage

其中config.yaml是用来配置访问权限,代理,文件存储路径等所有配置信息的,htpasswd用来保存用户的账号密码等息息,storage是用来存放npm包的。

config.yaml配置文件

#
# This is the default config file. It allows all users to do anything,
# so don't use it on production systems.
#
# Look here for more config file examples:
# https://github.com/rlidwka/sinopia/tree/master/conf
#

# path to a directory with all packages
storage: ./storage  //npm包存放的路径

auth:
  htpasswd:
    file: ./htpasswd   //保存用户的账号密码等信息
    # Maximum amount of users allowed to register, defaults to "+inf".
    # You can set this to -1 to disable registration.
    max_users: -1  //默认为1000,改为-1,禁止注册

# a list of other known repositories we can talk to
uplinks:
  npmjs:
    url: http://registry.npm.taobao.org/  //默认为npm的官网,由于国情,修改 url 让sinopia使用 淘宝的npm镜像地址
    
packages:  //配置权限管理
  '@*/*':
    # scoped packages
    access: $all
    publish: $authenticated

  '*':
    # allow all users (including non-authenticated users) to read and
    # publish all packages
    #
    # you can specify usernames/groupnames (depending on your auth plugin)
    # and three keywords: "$all", "$anonymous", "$authenticated"
    access: $all

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

    # if package is not available locally, proxy requests to 'npmjs' registry
    proxy: npmjs

# log settings
logs:
  - {type: stdout, format: pretty, level: http}
  #- {type: file, path: sinopia.log, level: info}

# you can specify listen address (or simply a port) 
listen: 0.0.0.0:4873  ////默认没有,只能在本机访问,添加后可以通过外网访问。

部分配置字段意义

storage: 仓库保存的路径

web: 是否支持WEB接口

auth: 验证相关

uplinks: 配置上游的npm服务器,主要是用于请求的仓库不存在时去上游服务器拉取

packages: 配置模块/包的发布(publish)、下载(access)的权限等

listen: 配置监听端口与主机名

auth配置

max_users: -1表示我们将最大用户数设置为-1,表示禁用 npm adduser 命令来创建用户,不过我们仍然可以通过当前目录下的 htpasswd 文件来初始化用户。
示例:


yorkie:{SHA}?????????????????=:autocreated 2016-02-05T15:33:46.238Z

weflex:{SHA}????????????????=:autocreated 2016-02-05T15:39:19.960Z

james:{SHA}????????????????=:autocreated 2016-02-05T17:59:05.041Z

上面的加密算法也很简单,就是简单的SHA1哈稀之后再转换成 Base64 输出就好,后面跟着的只是表示时间。

packages配置

配置大致分为两个部分,一个是以 @weflex/* 为开头的,另一个则是通配符 *。

这个当然就是对 package.json 中的 name 字段进行匹配,比如 @weflex/app 将匹配第一个配置,而 express 则匹配第二个。

这里这么配置的意义在于:一般团队或者公司的私有项目,会采用不同的权限控制,于是这里借用了 NPM 的 scoped name 即 @Company 的形式,例如 @weflex/app 即表示 WeFlex 下属的 app 项目了。

接下来,每一个命名过滤器(filter)下都有三项基本设置:

  • access: 表示哪一类用户可以对匹配的项目进行安装(install)

  • publish: 表示哪一类用户可以对匹配的项目进行发布(publish)

  • proxy: 如其名,这里的值是对应于 uplinks 的

对于1和2的值,我们通常有以下一些可选的配置:

  • $all 表示所有人都可以执行对应的操作

  • $authenticated 表示只有通过验证的人可以执行对应操作

  • $anonymous 表示只有匿名者可以进行对应操作(通常无用)

或者也可以指定对应于之前我们配置的用户表 htpasswd 中的一个或多个用户,这样就明确地指定哪些用户可以执行匹配的操作
配置完成后,再运行:

$ sinopia -c config.yml

客户端使用

强烈推荐使用nrm来管理自己的代理。

安装nrm:

全局安装nrm可以快速修改,切换,增加npm镜像地址。

$ npm install -g nrm # 安装nrm
$ nrm add XXXXX http://XXXXXX:4873 # 添加本地的npm镜像地址
$ nrm use XXXX # 使用本址的镜像地址

nrm的其他命令:

$ nrm --help  # 查看nrm命令帮助
$ nrm list # 列出可用的 npm 镜像地址
$ nrm use taobao # 使用`淘宝npm`镜像地址

安装包

安装完成.之后你通过npm install 安装的包,sinopia都会帮你缓存到本地了.试一下吧。

mkdir test && cd test
npm install lodash # sinopia发现本地没有 lodash包,就会从 taobao镜像下载
rm -rf node-modules # 删除目录
npm insatll lodash # 第二次安装就会从缓存下载了,速度很快

创建用户与发布包

创建新用户

1.确保自己已经切换到配置的代理

➜  ~ nrm ls

  npm ---- https://registry.npmjs.org/
  cnpm --- http://r.cnpmjs.org/
  taobao - http://registry.npm.taobao.org/
  nj ----- https://registry.nodejitsu.com/
  rednpm - http://registry.mirror.cqupt.edu.cn
  npmMirror  https://skimdb.npmjs.com/registry
* sinopia  http://192.168.1.200:4873/

2.运行npm adduser,填写信息,注册账号。如果已经有账号,直接运行npm login即可。

➜  ~ npm adduser
  Username: test
  Password:

3.运行$ npm publish发布新包。

总结

  • 到此为止吧,剩下的坑自己踩吧,多踩坑才能多成长。
  • 保存好你的 htpasswd 文件,不要泄漏到任何公有仓库中去。
  • 以上的情况并没有考虑在遇到一些黑客攻击的情况下,所以为了尽量保证代码的安全,可以在前端加一层 Nginx 然后配置 SSH 公钥来作为双层验证。

@Pines-Cheng Pines-Cheng added the npm label Mar 3, 2017

@WangShuXian6

This comment has been minimized.

Show comment
Hide comment
@WangShuXian6

WangShuXian6 Apr 4, 2018

已缓存的公共仓库的包如何更新呢?

WangShuXian6 commented Apr 4, 2018

已缓存的公共仓库的包如何更新呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment