IPFSの本番環境設定

IPFSを本番環境で使う機会があり、いろいろ調べたのでナレッジを共有します。

## 1. 環境変数設定
まず`IPFS_PATH`を指定します。ここにIPFSのリポジトリが作られます。
指定なしだと`$HOME/.ipfs`に作られます。バックアップ＆リストアを見越して適切な場所を設定します。

次に`IPFS_FD_MAX`を指定します。これはファイルディスクリプタの最大値を指定するもので、[go-ipfsのデフォルト設定](https://github.com/ipfs/go-ipfs/blob/master/cmd/ipfs/util/ulimit.go)に合わせて`8192`を設定します。

```
export IPFS_PATH=/data/ipfsrep
export IPFS_FD_MAX=8192
```

## 2. IPFSの初期化
IPFSを初期化するときは必ず`-- profile server`オプションをつけます。これによりプライベートネットワーク内で他のノードを探すような通信が発生しません。

```
ipfs init —- profile server
```

参考: [Getting Started > Initialize the repository](https://docs.ipfs.io/introduction/usage/)

## 3. 設定ファイルの編集
`config`コマンドで設定するのが正攻法ですが、設定ファイルを直接編集する方が楽です。

```
vi $IPFS_PATH/config
```

まず`Addresses.API` と `Addresses.Gateway`を編集します。Gatewayの方が読み込み専用で、APIの方が書き込み可能です。
アクセス制限を設けたい場合は、許可するIPアドレスを個別に指定します。設けたくない場合は`0.0.0.0`を指定します。

```
"Addresses": {
　"API": [
　　"/ip4/127.0.0.1/tcp/5001",
　　"/ip4/169.254.20.75/tcp/5001"
  ],
  "Gateway": "/ip4/0.0.0.0/tcp/8080",
```

次に`Datastore.StorageMax`でIPFSのストレージサイズを設定します。

```
"StorageMax": "100GB"
```

続いて、GatewayのCROSを設定します。デフォルトで有効化されており、必要に応じて設定を変更します。

```
"Gateway": {
  "APICommands": [],
  "HTTPHeaders": {
    "Access-Control-Allow-Headers": [
      "X-Requested-With",
      "Range",
      "User-Agent"
    ],
    "Access-Control-Allow-Methods": [
      "GET"
    ],
    "Access-Control-Allow-Origin": [
      "*"
    ]
  },
```


最後に[IPFS Cluster](https://cluster.ipfs.io/)の[本番設定](https://cluster.ipfs.io/documentation/deployment/setup/)を参考に、必要な設定を追加します。

```
"Datastore": {
    "BloomFilterSize": 1048576,
...
Swarm: {
    "ConnMgr": {
        "HighWater": 1000,
        "LowWater": 250,
```

## 4. バックグラウンドで起動
開発目的で、とにかく簡単に起動したい場合は、以下のコマンドで起動します。

```
# Start
ipfs daemon > $IPFS_PATH/ipfs-`date +%Y%m%d%H%M%S`.log &

# Stop
ps ax | grep ipfs | head -n 1 | awk ‘{print $1}’ | xargs kill
```
一方、本番運用ではデーモン化します。
まずシステムユーザを作成し、設定ファイルを新規作成します。

```
adduser — system — group ipfs
chown -R ipfs:ipfs $IPFS_PATH
vi /lib/systemd/system/ipfs.service
```
そして、[このGithub Issue](https://github.com/ipfs/go-ipfs/issues/1430)を参考に設定を記載します。

```
[Unit]
Description=IPFS daemon
After=network.target
Requires=network.target

[Service]
Type=simple
User=ipfs
RestartSec=1
Restart=always
Environment=IPFS_PATH=/data/ipfsrep
Environment=IPFS_FD_MAX=8192
ExecStart=/usr/local/bin/ipfs daemon

[Install]
WantedBy=multiuser.target
```

## 5. HTTPS対応
IPFSノードはHTTPSをサポートしていません。
なので、ロードバランサーやプロキシサーバでSSLオフロードします。

参考: 
[NGINXのリバースプロキシ設定](https://hackernoon.com/public-ipfs-node-behind-nginx-reverse-proxy-5682747f174b)
[Azureのロードバランサー設定](https://medium.com/@t.tak/build-https-support-load-balancer-on-azure-81e111e58d98)

## 6. Swarmの停止
IPFSは起動時に`bootstrap peer list`に載っているノードと接続を試みます。

```
ipfs bootstrap list
```
接続したノードから別ノードの情報を取得し、繰り返すことで、多くのノードと接続します。
もし、IPFSノードを読み込み専用なGatewayとして使うなら、この通信を遮断するのが良いです。通信費を削減できます。

方法としては`4001 port`の`Inboud`と`Outbound`を閉じるだけです。

## 7. バックアップ＆リストア
`$IPFS_PATH`配下全てがバックアップ対象です。
リストアは、バックアップを展開し`$IPFS_PATH`に展開先を指定するだけでできます。

## 8. クラスター構成
必要ならば設定します。

参考:
[IPFS Cluster](https://cluster.ipfs.io/)
[Using IPFS Cluster Service for Global IPFS Data Persistence](https://medium.com/@rossbulat/using-ipfs-cluster-service-for-global-ipfs-data-persistence-69a260a0711c)