Verdaccioを使って簡単local npm registryを構築する

ローカルにnpm registryを構築する方法はいくつかありますが、結構有名らしい[Verdaccio](https://verdaccio.org/)を使って構築するための備忘録
ブログとかQiitaにも記事はあるんだけど肝心な設定が抜けていたりしていたのでその辺も載せておきます

## 目次
1. [構築環境](#構築環境)
1. [必要なパッケージのインストール](#必要なパッケージのインストール)
  - [npmのインストール](#npmのインストール)
  - [verdaccioのインストール](#verdaccioのインストール)
1. [verdaccioの設定](#verdaccioの設定)
  - [標準のサービスファイルをsystemdにコピーする](#標準のサービスファイルをsystemdにコピーする)
  - [コピーしたサービスファイルを修正する](#コピーしたサービスファイルを修正する)
1. [一旦verdaccioを起動させる](#一旦verdaccioを起動させる)
  - [configファイルを修正する](#configファイルを修正する)
  - [local registryのproxyを追加](#local registry のproxyを追加)
  - [npm package問い合わせをlocal優先にする](#npm package問い合わせをlocal優先にする)
  - [外部アクセスを受け付けるにはこれが必須](#外部アクセスを受け付けるにはこれが必須)
1. [verdaccioをサービスに登録する](#verdaccioをサービスに登録する)
  - [起動と自動起動の設定](#起動と自動起動の設定)
  - [動作確認](#動作確認)
1. [registryを追加する](#registryを追加する)
  - [パッケージ毎に分けたい場合](#パッケージ毎に分けたい場合)
  - [グローバルに設定する場合](#グローバルに設定する場合)
  - [npmコマンド実行時に毎回registryの引数を渡す場合](#npmコマンド実行時に毎回registryの引数を渡す場合) 
1. [npm userを作成する](#npm userを作成する)
  - [新規作成の場合](#新規作成の場合)
  - [ログインする場合](#ログインする場合)
1. [local registryに公開・削除する](#local registryに公開・削除する)
  - [公開](#公開)
  - [公開されているパッケージを削除する](#公開されているパッケージを削除する)

## 構築環境
- Linux mint 19.1
- node.js 8.10.0
- npm 3.5.2

## 必要なパッケージのインストール
### npmのインストール
Verdaccioはnpm packageの一つなので大前提としてnpmをインストールしておく必要があります
(インストール済みであればスキップ)
`sudo apt update && sudo apt install -y npm`

### verdaccioのインストール
npmをインストールし終わったらverdaccioをグローバルインストールします
`sudo npm i -g verdaccio`

## verdaccioの設定
### 標準のサービスファイルをsystemdにコピーする

```
sudo cp /usr/local/lib/node_modules/verdaccio/systemd/verdaccio.service /etc/systemd/system/
```

[Server Configuration・Verdaccio](https://verdaccio.org/docs/en/server-configuration#using-systemd)を参考にしていたのですが、どうやらLinux mintではサービスファイルの格納ディレクトリやsystemdディレクトリが違っていたので上記の様になりました
ディストロによって公式と同じディレクトリにあり、変更する必要がないかもしれないので適宜読み替えてください

公式のコマンドはこちら

```
sudo cp /usr/lib/node_modules/verdaccio/systemd/verdaccio.service /lib/systemd/system/
```

### コピーしたサービスファイルを修正する
このままだとサービスを実行してもエラーを吐かれてしまうので下記画像の様に書き換えます

![verdaccio_service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230050/a0984db1-03fd-a6fd-1a3b-de7cf840db20.png)

**ExecStart**に指定している実行ファイルの場所やconfigファイルの場所を変更しています
(verdaccioの実体がディストロによって変わるのか分かりませんが、Linux mintでは上記ディレクトリに配置されています)

configについては後程verdaccioを実行すると、ホーム直下の**.config/**以下に自動生成されるのでそれを割り当てています

## 一旦verdaccioを起動させる
`verdaccio`と打ち込んで起動させます
すると先ほども書いたように**$HOME/.config/verdaccio/config.yaml**が生成されているかと思います

### configファイルを修正する
configファイルの生成を確認したら停止させるか別のターミナルを開き、以下の様に修正します
(ユーザー名が**gn5r**なので適宜読み替えてください)

```yaml:$HOME/.config/verdaccio/config.yaml
storage: /home/gn5r/.local/share/verdaccio/storage
plugins: ./plugins

web:
  title: Verdaccio
storage: /home/gn5r/.local/share/verdaccio/storage
plugins: ./plugins

web:
  title: Verdaccio

auth:
  htpasswd:
    file: ./htpasswd

uplinks:
  npmjs:
    url: https://registry.npmjs.org/
  local:
    url:  http://localhost:4783/

packages:
  '@*/*':
    # scoped packages
    access: $all
    publish: $authenticated
    unpublish: $authenticated
    proxy: local

  '**':
    access: $all

    publish: $authenticated
    unpublish: $authenticated

    proxy: local
server:
  keepAliveTimeout: 60

middlewares:
  audit:
    enabled: true

listen: 0.0.0.0:4783
```

### local registry のproxyを追加
これがキモでlocal registryと公式registryを両立させるためにproxyを追加

```
uplinks:
  local:
    url:  http://localhost:4783/
```

### npm package問い合わせ先をlocal優先にする
この部分でパッケージ問い合わせをlocal registry優先にしています。見つからなかったら公式registryに問い合わせる感じ

```
packages:
  '@*/*':
    # scoped packages
    access: $all
    publish: $authenticated
    unpublish: $authenticated
    proxy: local

  '**':
    access: $all

    publish: $authenticated
    unpublish: $authenticated

    proxy: local
```

### 外部アクセスを受け付けるにはこれが必須

この設定をしないと開発マシンからverdaccioサーバーのwebページにアクセスできなかったり不便なのでほぼ必須です
(最初ちゃんと調べずにやっていたらエラーが出て、それをTwitterでボヤいたら公式が教えてくれました)
また、ポートを変えたい場合もここで設定できます(デフォルトは**4873**)

```
listen: 0.0.0.0:4783
```

## verdaccioをサービスに登録する
### 起動と自動起動の設定
以下3つを実行しverdaccioを起動&自動起動を有効にする
`sudo systemctl daemon-reload`
`sudo systemctl start verdaccio`
`sudo systemctl enable verdaccio`

### 動作確認
ポートを変えていなければブラウザを開いて**IPアドレス:4873**にアクセスするとverdaccioのwebページが表示されればOK

![verdaccio_web.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230050/dbfc7831-aaae-b3f2-67a5-c553d9cbd5c7.jpeg)

(画像ではポートを変えてあるので**4783**にアクセスしています)

## registryを追加する
[ここ](https://verdaccio.org/docs/en/installation#basic-usage)にも書いてありますが、構築したregistryを追加する方法はいくつかあるようです

### パッケージ毎に分けたい場合
パッケージ(プログラム)以下のpackage.jsonがあるディレクトリの`.npmrc`に`registry=http://IPアドレス:4783`を追記(無ければ作成)

### グローバルに設定する場合
`npm set registry http://IPアドレス:4783`を実行

### npmコマンド実行時に毎回registryの引数を渡す場合
各npmコマンド実行時に`--registry http://IPアドレス:4783`を付与

## npm userを作成する
### 新規作成の場合
`npm adduser --registry http://IPアドレス:4783`
ユーザー名とパスワード、Emailを入力すれば完了(パスワードは1回入力)

### ログインする場合
別マシンで作成したユーザーを使いたい場合は
`npm login --registry http://IPアドレス:4783`

## local registryに公開・削除する
設定でlocalを優先にしているので、試しに`--registry`を付けずにpublish、unpublishしてみたけど途中で止まってしまったので、`--registry`は必須かと思います
(多分公式のregistryにも投げているのかもしれない。公式のaccessTokenは無いので認証部分で止まっているのかと推測しています)

### 公開
package.jsonがあるディレクトリで
`npm publish --registry http://IPアドレス:4783`
### 公開されているパッケージを削除する
`npm unpublish --force パッケージ名 --registry http://IPアドレス:4783`