標籤:

Sinopia | 從零開始搭建npm倉庫

使用 Node.js 開發商業項目,其中除了技術選型,最令人糾結的一個問題就是私有NPM怎麼託管,有的人說:

我用 git+ssh 這種方式直接引用到 GitHub 項目地址

嗯,這種方式可行,也最簡單,但真真的太爛了,姑且不說不能使用 semver,關鍵還是 url 太丑,如果是強迫症真的沒法忍~

我用 cnpm 代理

暫且不論 cnpm 只是作為鏡像使用,其實這個方案缺點就挺多的,用的人多,速度不一定快,緩存,關鍵是不支持發布包以及登陸、註冊,再加上配置過於複雜。

那好,我是土豪,我要買 npm on-site

說實在的,我就是從這個方案跳出來的,因為 npm 的服務對於國內團隊真的是挺貴,而且還死慢,得不償失,性價比太低。

好,下面進入正題了,我今天就是要給你們安利新get的神器:Sinopia,首先,要介紹一下這個項目的作者:

是的,看上去是一個大神,也是一隻貓~ 往社區內貢獻過很多代碼,包括 jshttp, markdown-it 等等,也是 Node.js 核心代碼庫的活躍貢獻者。

是的,我今天要安利的項目大家都看到了,就是1779顆星星(?)的那個項目,不過這裡插句題外話,看到項目裡面基本都不怎麼更新了,不過好在我在使用的過程沒怎麼遇到 Bug。

首先,我先大概講講 Sinopia 的思路,我大概掃過一眼代碼,大致有以下三點:

  1. 通過兼容官方的 Registry 的介面來對終端中 NPM 命令的兼容,從而不需要使用像 cnpm 這樣的命令

  2. 正是由於 npm 支持諸如 --registry 以及 .npmrc 這樣的配置文件,所以才使得上一條可以正常使用,而不需要任何 hacky 的代價

  3. 官方的 npm 使用 CouchDB 作為倉庫資料庫(大致聽說),不過 Sinopia 將直接使用文件系統來作為存儲結構,這樣可以非常方便我們對緩存以及發布的倉庫進行查看

上圖就是一個 Sinopia Registry 的倉庫截圖。

下面就開始搭建 Registry 伺服器,其實作者已經將步驟簡化到不能再簡單了,如果本地搭建,直接通過:

$ npm install sinopia -g

然後再通過:

npm set registry localhost:4873/

來設置客戶端使用的npm代理,然後就能正常使用了,接下來,為了可以發布你的私有庫,你需要一個用戶名:

npm adduser --registry localhost:4873

按照 npm 所給的提示輸入完畢後,需要再登陸一次(之前的 adduser 相當於註冊用戶):

npm login

同樣根據提示完成登陸,這個時候,打開 ~/.npmrc 你就應該能看到更新後的配置文件,接著你就可以使用 npm publish 來發布代碼庫到你的這個私有倉庫給你的團隊小夥伴使用了。

事情還沒完,眼睛尖的小夥伴可能已經發現:

誒?npm adduser 貌似不需要任何驗證就能添加,那豈不是所有人都能訪問到我的私有倉庫代碼了嗎?

答案是 YES,不過不用著急,奴家這就說說怎麼來配置驗證與角色許可權。

首先你在啟動 sinopia 的時候,可以指定一個配置文件,在裡面可以設置一些像:

  • storage: 倉庫保存的路徑

  • web: 是否支持WEB介面

  • auth: 驗證相關

  • uplinks: 配置上游的npm伺服器,主要是用於請求的倉庫不存在時去上游伺服器拉取

  • packages: 配置模塊/包的發布(publish)、下載(access)的許可權等

  • listen: 配置監聽埠與主機名

這裡著重講一講 auth 和 packages 的用法。

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

最後一行特別重要,這裡我們將最大用戶數設置為-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

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

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

上面的加密演算法也很簡單,就是簡單的SHA1哈稀之後再轉換成 Base64 輸出就好,後面跟著的只是表示時間。

好,接下來說一下 packages:

packages:

@weflex/*:

access: $authenticated

publish:

- admin

- yorkie

*:

access: $all

publish: $authenticated

proxy: npmjs

可以看到上面的配置大致分為兩個部分,一個是以 @weflex/* 為開頭的,另一個則是通配符 *。

這個當然就是對 package.json 中的 name 欄位進行匹配,比如 @weflex/app 將匹配第一個配置,而 express 則匹配第二個。

這裡這麼配置的意義在於:一般團隊或者公司的私有項目,會採用不同的許可權控制,於是這裡借用了 NPM 的 scoped name 即 @company 的形式,例如 @weflex/app 即表示 WeFlex 下屬的 app 項目了。

接下來,每一個命名過濾器(filter)下都有三項基本設置:

  1. access: 表示哪一類用戶可以對匹配的項目進行安裝(install)

  2. publish: 表示哪一類用戶可以對匹配的項目進行發布(publish)

  3. proxy: 如其名,這裡的值是對應於 uplinks 的

對於1和2的值,我們通常有以下一些可選的配置:

  1. $all 表示所有人都可以執行對應的操作

  2. $authenticated 表示只有通過驗證的人可以執行對應操作

  3. $anonymous 表示只有匿名者可以進行對應操作(通常無用)

  4. 或者也可以指定對應於之前我們配置的用戶表 htpasswd 中的一個或多個用戶,這樣就明確地指定哪些用戶可以執行匹配的操作

所以,上面 packages 的配置文件可以解讀為:

  1. 驗證過的用戶可以安裝 @weflex 下的包

  2. 名為 admin 或 yorkie 的用戶可以發布 @weflex 下的包

  3. 所有人都可以獲取到非 @weflex 下的包

  4. 驗證過的用戶可以發布非 @weflex 下的包

配置完成後,再運行:

$ sinopia -c config.yml

就能放心、安全地使用你的 NPM 包了。配置完成後,如果你設置了 web.enable 為 true 的話,還可以通過網頁的方式來瀏覽你的 Registry 情況。

另外,關於如何託管你的進程,你可以使用 docker, pm2 或者 forever 都可以。不過記住,千萬要保存好你的 htpasswd 文件,不要泄漏到任何公有倉庫中去。

至此,一個可以完整使用的 NPM Registry 伺服器就搭建完成,雖然文章很長,但是整個搭建過程真的很短,很簡單,希望可以給各位一個比較好的商業NPM以及NPM翻牆的解決方案。

不過,以上的情況並沒有考慮在遇到一些黑客攻擊的情況下,所以為了盡量保證代碼的安全,可以在前端加一層 Nginx 然後配置 SSH 公鑰來作為雙層驗證。

該文從我的微信公眾號拷貝:Sinopia | 從零開始搭建npm倉庫

推薦閱讀:

npm的應用場景,剛需在何處?簡單的寫寫頁面是否需要npm包管理工具?
Node快閃:npm模塊版本策略
IoT開發的利器,pi-sync
Node.js中的哪些庫讓你相見恨晚?
semver:語義化版本規範在 Node.js 中的實現

TAG:Nodejs | npm |