SinopiaでPrivateなnpmレポジトリを作成する方法

npmのCaching & Private Serverである [Sinopia](https://github.com/rlidwka/sinopia) を導入した際のメモ.

## Sinopiaの使いどころ

主なユースケースは下記:

+ 企業内のネットワーク等、開発者全員がInternetに接続可能ではないケースで, Proxyとして利用.
+ 開発において, 作成したNode.jsのパッケージをチーム内で共有したいが, Internetには晒したくないケースで, Private Repositoryとして利用.

まぁ恥ずかしがり屋さん達向けですね。

いくつか、このようなnpmをPrivate化するためのソフトはあるものの, 下記の理由によりSinopiaを選択.

1. 導入が用意(CouchDBとか不要)
1. クライアント側の設定変更が最小限

## 環境構築

### 前提

+ SinopiaをインストールするサーバにはUbuntuを利用.
 + とはいえ、基本的にはNode.jsの話なので、他のディストリやOSでも動くと思います(実際, Windowsでも問題なく動作はしました).
+ 事前にsinopia実行用のユーザを作っておく(面倒であればrootでも動くっぽいけど). (`sinopia` というユーザ名にしています)
+ サーバにはNode.jsがインストールされており, `npm install` が実行できる状態としておく.


```sh
$ sudo npm install -g sinopia
```

### 起動

```sh
$ sinopia
```

sinopiaを起動すると, 設定ファイル `${home}/sinopia/config.yaml` が勝手に作成される.
また, デフォルトではport 4873がsinopiaのサーバとなる.

### sinopia -> internet のproxy
Sinopiaを動作させているサーバが本家のNPMレジストリ registry.npmjs.org に対して, http proxyが必要な場合, 上記の設定ファイルの末尾に下記を追記した上で, sinopiaを再起動する.
(以下は, Proxyサーバがhttp://localhost:8082の場合の例)

```yaml:config.yml
http_proxy: http://localhost:8082/
https_proxy: http://localhost:8082/
no_proxy: localhost, 127.0.0.1
```

## 動作確認

+ `${home}/.npmrc` をエディタで開き, 下記を追記する.

```
registry=http://localhost:4873/
```

+ 次のコマンドを実行して確認してみる.

```sh
npm info npm
```

上記は「`npm`という名前のパッケージ情報の取得」を意味するため, sinopiaのCaching Serverとしての正常動作確認となる.


## 細かいサーバ設定

### nginxとの連動

Sinopiaの手前にReverse Proxyを作成する際のメモ.

ここでは, sinopiaが稼働しているマシン上で, nginxも稼働している前提とする.
(マシン名を `www.yourhost.com` とする).

クライアントからの `http://www.yourhost.com/npm/～～～` のリクエストをsinopiaにproxyする設定例.

*"/"の有無で結果が結構違う形になるので, 注意すること!*

+ `/etc/nginx/config/site-available/default` に下記を追記.

```sh:/etc/nginx/config/site-available/default
server {
  
  lisetn 80 default_server;

  ## 色々な設定
  ## :

  ## ★ 追記 ★
  location /npm/ {
    proxy_pass http://localhost:4873/;
  }

  ## ★ 追記 ★
  location /- {
    proxy_pass http://localhost:4873/-;
  }

```

`/npm/` だけでなく `/-` のlocationが設定されているのは, ユーザ作成時に叩く, `npm adduser` のリクエストについては, `.npmrc` に設定されているregistry URLのパス部分が無視されるため.
もう少しスマートな設定方法があるような気もしないでもないが, 取り合えず動作するということで...

+ `${home}/sinopia/config.yml` に下記を追記.

```yaml:config.yml
url_prefix: http://www.yourhost.com/npm
```
この設定でブラウザアクセスした際の.jsファイルや.cssファイルのリンクURLに `/npm` が付与されるようになる.

### クライアントから確認
上記により, 開発者側は, `.npmrc` に下記を書くことでSinopiaをnpmレポジトリとして利用可能になる.

```sh:.npmrc
registry=http://www.yourhost.com/npm/
```

また, クライアントのブラウザから, `http://yourhost.com/npm/` にアクセスするとSinopiaのWeb画面が開けるようになっている筈.

### Sinopiaをサービス登録

+ `sudo vim /etc/init.d/sinopia` でinitスクリプトを作成し, 内容を下記とする.

```sh:/etc/init.d/sinopia
#!/bin/sh
# chkconfig: 345 99 01
# description: my init.d file

SERVICE=sinopia
EXECUSER=sinopia
COMMAND=sinopia
OPTIONS="-c /home/$EXECUSER/sinopia/config.yaml"

start() {
    sudo -u $EXECUSER nohup sinopia $OPTIONS > /home/$EXECUSER/stdout.log 2>&1 &
    echo "service $SERVICE [start]"
}
stop() {
    pkill $COMMAND
    echo "service $SERVICE [stop]"
}
status() {
   PID=`pgrep $COMMAND | wc -l`
   if [ $PID -eq 0 ]; then
       echo "$SERVICE stop"
   else
       echo "running $SERVICE ..."
   fi
}

case $1 in
start)
       start
       ;;
stop)
       stop
       ;;
status)
       status
       ;;
restart)
       stop
       start
       ;;
*)
       echo "Usage: $SERVICE [start|stop|restart|status]"
       ;;
esac
exit 0
```

上記のスクリプトは[ここ](http://d.hatena.ne.jp/letitride/20121029/1351488131)を参考にしている.

+ 実行権限付与

```sh
$ sudo chmod 755 /etc/init.d/sinopia
```

+ 上記のスクリプトを登録(Ubuntuの場合)

```sh
$ sudo update-rc.d sinopia defaults
```

## Private レポジトリとしての活用

前提として, 実行端末の`${home}/.npmrc` に下記が記載されているものとする.

```:~/.npmrc
registry=http://www.yourhost.com/npm/
```

+ ユーザ作成

`npm adduser` コマンドをプロンプトから実行する.
ユーザ名, パスワード, emailアドレスを聞かれるので, 順に入力していくだけ.
(要はsinopiaが無い場合と一緒)

+ パッケージのpublish

package.jsonを作成し、`npm publish` を実行する.

成功すれば, `npm info (自作したパッケージ名)` のコマンドを実行することで上記でpublishしたパッケージが確認できる.

## その他のsinopiaの設定項目

config.yamlに記載可能な内容については, [SinopiaのGithubレポジトリにあるyamlファイル](https://github.com/rlidwka/sinopia/blob/master/conf/full.yaml)を参照するのが一番手っ取り早い.