IPFSを使って無料で静的サイトをホスティング（公開）してみる

# IPFSとは
_A peer-to-peer hypermedia protocol to make the web faster, safer, and more open._ ([参照元](https://ipfs.io/)(GitHubは[こちら](https://github.com/ipfs/ipfs)))

*IPFSは、オブジェクト（画像、記事、映像）を参照する時にどのサーバに保管されているかを調べるのではなく、全ての参照においてファイルのハッシュを使います。考え方としては、ブラウザで特定のページにアクセスしたい場合、IPFSはネットワーク全体に対して「このハッシュに対応するこのファイルを持っているか？」と問い合わせを行い、該当するIPFSのノードがファイルを返すことで、ページにアクセス可能になるという仕組みです。* （[参照元](http://postd.cc/an-introduction-to-ipfs/)）


さて、これだけでは意味がわからないが、[DEMO](https://www.youtube.com/watch?v=8CMxDNuuAiQ)を見てみると、画像や動画ファイルを管理するための分散型システムということがなんとなくわかる.

本稿では、IPFSで静的なウェブサイトを公開する方法にフォーカスし、IPFSが何であるかについては詳しく触れないでおく. 日本語なら[これ](http://postd.cc/an-introduction-to-ipfs/)が一番詳しいと思うので、IPFSが何者であるかは、そちらを参照していただきたい.

# 静的なサイトをホスティングしてみる

HTML/CSS/JavaScript のみで動くような静的なウェブサイトはどこに置くのが良いのだろうか. [netlify](https://www.netlify.com/)や[BitBalloon](https://www.bitballoon.com/)、[Neocities](https://neocities.org/)、といった簡単に無料から利用できるサービスはある（ちなみに余談だが、Neocitiesは、IPFSを利用している）. ただ、無料で利用するにはドメインの自由はきかない. 好きなドメインを利用したり、本格的に運用する場合は[Amazon S3](https://aws.amazon.com/jp/s3/)や[Google Cloud Storage](https://cloud.google.com/storage/?hl=ja)等々のサービスを利用することになるだろう. ただしお金がかかってしまう.

本稿ではIPFSとCloudflareを利用して無料でカスタムドメインでホスティングすることを目標とする. こんな変なことをしなくても良いと思いつつもIPFSが面白かったので使ってみる.

実際にホスティングしているのは[こちら](https://shuichi.tech)

## 大まかな流れ
1. IPFSをセットアップする.
2. ファイルをIPFSにaddする. [追記: このときにpinをしておく]
3. IPNSにPublishする.
4. サイトの修正・更新をするときは2, 3を繰り返す.
5. DNSでURLの設定をする.

## 詳しい手順
### 1. `IPFS` をセットアップする.
- インストール方法についての[ドキュメント](https://ipfs.io/docs/getting-started/)
    - golangが入っていれば `go get -u -d github.com/ipfs/go-ipfs` で入れられる.
    
```bash
# PATHを通す必要があれば
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:$GOPATH/bin

go get -u -d github.com/ipfs/go-ipfs
cd $GOPATH/src/github.com/ipfs/go-ipfs
make install

ipfs init
```

### 2. ファイルをIPFSにaddする
- 公開したいサイトのフォルダを `Mypage` とする.
- [追記： ここでpinしておかないと、一定時間経つとコンテンツにアクセスできなくなってしまう]

```console
$ ipfs add -r Mypage/
added QmWfWKbnzoiubwsig2f2SsojxZXsrg7ju7nHx4vqNyd8Z Mypage/README.md
added QmYYXM85MrvmoxYsa8i99cc8dvbBUtGM9e8M1v6dsaUt9 Mypage/css/main.css
added QmSKHX8gEpGxCdLJao9y7VUpXSG59L6Mo57X2AL23E652 Mypage/index.html
added Qmd9Df6WSVWTTGtu2KZVxf3FMcYrrogmtic3cpufNZws7 Mypage/js/main.js
added QmNyd25QmdNgzbhBgjTn3AXiLjkptXuTuXwhy5vXrzcsw Mypage/css
added QmXz6vdZVDcfijimBSF7BT2QACG74mRYnnKZVgvnhT7Ni Mypage/js
added QmWYRPAzjqBx5C8Fo5vh1ZHbLaXkbiUSb9LVmgh2vyGh6 Mypage
$
$ ipfs daemon
$
$ ipfs pin add -r QmWYRPAzjqBx5C8Fo5vh1ZHbLaXkbiUSb9LVmgh2vyGh6
....
```


- `ipfs add -r mypage/` とすると各ファイルごとのハッシュが返ってくる. この一番下にあるハッシュを利用する.
- `ipfs daemon` を行うと、P2Pネットワークに繋がり、先ほどaddしたコンテンツが外部に伝わっていく.
- `http://localhost:8080/ipfs/QmWYRPAzjqBx5C8Fo5vh1ZHbLaXkbiUSb9LVmgh2vyGh6` のようにブラウザでアクセスすると確認ができる. （ここに書いてあるhashはデタラメなのでアクセスはできない）
- `https://gateway.ipfs.io/ipfs/QmWYRPAzjqBx5C8Fo5vh1ZHbLaXkbiUSb9LVmgh2vyGh6` のようにアクセスして見れるようになればOK.

### 3. IPNSにPublishする

```console
$ ipfs name publish QmWYRPAzjqBx5C8Fo5vh1ZHbLaXkbiUSb9LVmgh2vyGh6
Published to Qmd9M1UXKudp3ydXrgDbEU8zEThWbuvTnJ1wUwfZRtGDb: /ipfs/QmWYRPAzjqBx5C8Fo5vh1ZHbLaXkbiUSb9LVmgh2vyGh6
```

- 2で起動したdaemonは動かしたままで、別ウィンドウでPublishする.
- IPFSはコンテンツを編集すると、ハッシュが変わるので、サイトの更新をするたびにアドレスが変わってしまう. そこで、IPNSを利用する. これは、コンテンツのハッシュの代わりに自分のPeerId（上の例でいうと `Qmd9M1UXKudp3ydXrgDbEU8zEThWbuvTnJ1wUwfZRtGDb` ）を識別子に利用する仕組みのこと.
- `ipfs name publish QmWYRPAzjqBx5C8Fo5vh1ZHbLaXkbiUSb9LVmgh2vyGh6` を実行する. すると、`Published to Qmd9M1UXKudp3ydXrgDbEU8zEThWbuvTnJ1wUwfZRtGDb: ....` と表示されるので、このハッシュ（PeerId）を使って `https://gateway.ipfs.io/ipns/Qmd9M1UXKudp3ydXrgDbEU8zEThWbuvTnJ1wUwfZRtGDb` のようにアクセスするとサイトが公開されているのが確認できる. 反映までに数分かかるかもしれない.

### 4. サイトの修正・更新をするときは2, 3を繰り返す

- ファイルの変更があるときは、 `ipfs add -r Mypage/` をして、新しく発行されたhashを利用して、 `ipfs name publish <newhash>` を実行すると、同じURLでアクセスできる.

### 5. DNSでURLの設定をする

今のところ、gateway.ipfs.ioのドメインでグローバルに公開されている. でもどうせなら、自分の持っているドメインで公開したくなる. これはCloudflareとかを利用すると無料でできる. もちろんドメイン自体はどこかしらで取得しなければならない. ちなみに[Freenom](http://www.freenom.com/ja/index.html)を利用すればドメインも無料で取得できる（評判はどうなのか知らないが）.

Cloudflareを利用したので、その説明をする. 今回は https://shuichi.tech というURLに公開してみる. オレンジの雲を有効にしておくと、Cloudflareがいい感じにSSLにしてくれる.

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122365/e8b6c877-3360-8a33-932c-0f66a3c70398.png)


次にTXTを選択して、先ほどと同様に `shuichi.tech` （ここは自分のドメインに変えてください）と入力して、さきほど `ipfs.io` と入力した欄には `dnslink=/ipns/Qmd9M1UXKudp3ydXrgDbEU8zEThWbuvTnJ1wUwfZRtGDb` (`Qmd9M1UXKudp3ydXrgDbEU8zEThWbuvTnJ1wUwfZRtGDb` はさきほど得た自分のPeerId)を入力して確定する. あとは反映されるのを待つだけ.

もしかするとこのままでは、リダイレクトループでうまくいかないかもしれない. 下の画像のように設定を加えておく.

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122365/84d99946-d635-e984-7796-8a01f4db45ad.png)


もし証明書周りで怒られたら、下の画像のように _FULL_ にすると解決するかもしれない. 

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122365/8727f6a9-ea77-37c8-e604-a2441bb3dcd0.png)


#### 備考

ただ、IPNSを利用すると遅くなったり、不安定なことが多かったので、公開するときはIPFSを利用する方が実用的なのかもしれない. 更新して公開できる準備ができたら、`ipfs add -r <FILE>` を実行して得たハッシュを元に、Cloudflare等にてDNSの設定を都度行う方が動作は安定するのかもしれないと感じた. 実際に自分で公開しているものはIPNSではなくIPFSを利用している.


# まとめ
IPFSはP2Pのファイル管理システムのようなイメージで、画像や動画に関しては高速で表示することができて面白い. 最近はBlockchainや分散化というワードが流行ってきており、こういう技術が注目されている. 概念や仕組みをちゃんと理解するのは難しいが、実際に動かしてみたり利用してみると、なんとなくわかってくる.

BlockchainとIPFSを絡めるとどうなるのだろう、と気になる方は[こちら](https://github.com/howardwu/IPFS-Ethereum-Storage)が参考になるかもしれない.