Mastodon のインスタンス作成時につまづいたところメモ

Mastodon は自分用のインスタンスを作成してこそ華。と思ってローカルの VM で動かしてみたり、[www.mofgao.space](https://www.mofgao.space) を立ててみたりしていました。
インスタンス構築の記事はもういっぱいあってそれらを参照して貰うとして、つまづいたところだけをメモ程度に書き残しておきます。

#対象

2017年 4月15日時点での git repository main。（メール周りは 4月13日に試行錯誤していたもの）
開発の方もすごい勢いで進んでいるので 3日後くらいには別物になっているかもしれません。
この記事に書いてあることが通用するとは限りません。

#基本方針

Mastodon のリポジトリに含まれている docker-compose & Dockerfile を使って、Docker コンテナで動作させます。
Docker だからコマンドポンで動くんだろと思っていたら意外とつまづいたというのがこの記事の趣旨となります。

## 構成知識

一人サーバーモードで Mastodon を動かす分には Docker ＆ docker-compose で問題ないのですが、多人数で扱うインスタンスにしようとするといくつかの追加要素を用意することになります。

+ メールサーバー
    + ユーザー登録時に必要
    + メール通知を利用したいとき
+ httpプロキシサーバー
    + https を提供するため
    + ストリーミングAPIを提供するため
    + ポート直指定をさけるため
+ S3 / minio といった S3 互換サーバー
    + 別になくてもいい
    + データ永続化の一環
    + アイコンや投稿画像はここからダウンロードされるので別サーバーにすると負荷が分散できる
    + これに対して media URL が張られる~~ので後で変更はたぶん無理~~(後付けで public/system/ のファイルをコピーしたら行けたというコメントをもらいました)

## データ永続化

Docker コンテナの特性上明確にデータの永続化をしていないと `docker-compose up -d` 時にコンテナが新規作成された場合とかに全部消えてしまいます。

永続化すべきデータは以下の 4つ

+ postgres の DB データ
+ redis の DB データ
+ /mastodon/public/assets
    + WEBページを構成する静的なデータ (html, css, js等)
+ /mastodon/public/system
    + S3 設定をしないとメディアファイルはここに置かれる

docker-compose の中を見ると postgres と redis の永続化はコメントアウトされています。有効にしておくのが良いでしょう。(最初の罠)
永続化の保存場所が `./public/` 等 docker-compose.yml があるパス(＝起動位置＝リポジトリclone場所)になっています。root 権限で書き込まれる事もあってここにあると面倒なので、どっか別な場所にまとめて置くと良いでしょう。(/var/lib/mastodon/ とか）

そもそもで postgres と redis は別サーバーに用意して利用した方が良さそうですね。

永続化さえちゃんとしていれば Mastodon 本体の更新も安心してできます。

## 環境ファイルと起動

各種設定を `.env.production` に書いて起動するのですが、最初この設定がコンテナ内に保存されている物だと思い込んでいて変更の度に `docker-compose build` していました。
よく見たら、`docker-compose` 内で起動時にこのファイルを使って環境変数を設定しているので、`.env.production` の編集後は `docker-compose up -d` だけで良いことがわかりました。

先の永続化データと `.env.production` のバックアップを取っておけば状態復帰は容易そうですね。


# つまづいたところ

メールとオブジェクトストレージ(S3)の設定についての解説があまりないので引っかかりました。
うまくいかない系はだいたいここ。

## メール設定

利用するメールサーバーとして mailgun.org を使った設定が `.env.production.sample` に参考として書かれています。mailgun の利用登録(無料コースあり)をしてここを使うのが一番手軽だと思います。

それ以外の MTA を使う場合でも TLS port 587 とログインが使える場合はやはりそのまま行けるので特に問題はありません。
(最終的に私はさくらのメールボックスを使いました)

一番の問題は「ローカルに MTA がいるので 25番で SMTP を使おう」とする場合です。
TLS/SSL を無効にして port 25 を使うので以下の様な設定になります。

```ini
SMTP_SERVER=localmail
SMTP_PORT=25
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=
SMTP_AUTH_METHOD=plain
SMTP_OPENSSL_VERIFY_MODE=none
SMTP_ENABLE_STARTTLS_AUTO=false
```

でもこれがうまく動きませんでした。

local MTA についての議論は以下の issue で展開されています。
https://github.com/tootsuite/mastodon/issues/772

質問者のワークアラウンドパッチである `config/environments/production.rb` 内の `:user_name` と `:password` をコメントアウトするというのが一番すっきりと動作させることができました。

SMTP ではなく sendmail を使おうとした場合も一悶着ありそうですね。

メール設定が失敗している場合は sidekiq コンテナのコンソールにエラーが表示されます。
以下の様にして確認することになります。

```
 # docker logs mastodon_sidekiq_1
```
コンテナ名は環境に応じて。


## minio (S3互換) 設定

メディアファイルの置き場所として minio を使おうとしてのですが、情報が少なくてひっかかりました。
minio は別サーバーの media.mofgao.space として Docker で設置しています。また、Mastodon 本体 (www.mofgao.space) が https なので、そこに埋め込まれる media サーバーとしても https で揃えなくてはいけないため nginx リバースプロキシを同じく Docker コンテナで用意しています。

`.env.production` の設定はこんな感じ。

```ini
# S3 (Minio Config (optional) Please check Minio instance for details)
S3_ENABLED=true
S3_BUCKET=mofgao
AWS_ACCESS_KEY_ID=............
AWS_SECRET_ACCESS_KEY=..........................
S3_REGION=us-east-1
S3_PROTOCOL=https
S3_HOSTNAME=media.mofgao.space
S3_ENDPOINT=http://media.mofgao.space:****/
```

`S3_PROTOCOL` と `S3_HOSTNAME` はこれメディアファイルへのアクセスURLとして Mastodon サイトに埋め込まれるもの。上記指定だと `https://media.mofgao.space/(バケット名)/～` という名前でアイコンや画像が埋め込まれます。
で、S3 ではなく minio の場合は `S3_ENDPOINT` を追加で指定しなくてはいけません。おそらく S3 の場合は AWS-SDK が endpoint を指定してくれるのだけれども、minio の場合はそこにないので手で指定しろということなのでしょう。

つまづいたのはこの `S3_ENDPOINT` に https が指定できなかった事にあります。
やむを得ず http のポートも開けて Mastodon からのアクセスポートとしています。

Paperclip の都合っぽいんだけれども深くは追っていません。
私の勘違いかもしれません。

S3周りのエラーは画像登録時(アカウントアイコン設定とか)に web コンテナのコンソールとして表示されます。以下のコマンドで確認します。

```
 # docker logs mastodon_web_1
```
コンテナ名は環境に応じて。



## nginx リバースプロキシ設定

https を利用したり、ストリーミングAPI にパスを与える場合は nginx をフロントにしてリバースプロキシを設定するのがお勧めです。
リバースプロキシを用意しない場合は `http://localhost:3000` とかやって mastodon に直接アクセスするのですが、この時ストリーミング API が `http://localhost:4000` になるので `.env.production` の `STREAMING_API_BASE_URL` で設定しないといけないのではないかと思います。ストリーミングAPIを別サーバーにした場合などは設定必須かと。

nginx でのリバースプロキシ設定については Mastodon の Production guide に書かれているので参考にする形で良いと思います。
Websocket 周りの設定をお忘れ無く。
https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Production-guide.md


# トラブルシュート

(Apr.18.2017 - 追記)
実際に遭遇したトラブルというか自分のミスについても記録しておきます。

## バージョンタグを使おう

Mastodon のリポジトリを github から clone してそのまま使っていたのですが、どうしても動かない状況に遭遇しました。
エラーからソースコードを追いかけていったら明らかなバグを見つけたのですが、そのバグを見つけている間に修正コードが commit されていました。

要するに clone してそのままの master は鋭意開発中なため、希に壊れることがあります。
開発参加ではなく、動かしたいという利用目的の場合はバージョンタグを checkout してから使いましょう。

## DB マイグレーションを忘れずに

どのメンテナンスをしたタイミングかは忘れましたが、なんかちょっと流れが悪いなあと思っているうちに TL が全く流れてこない現象に出会いました。
sidekiq を見てみるとキューがことごとく失敗してリトライを繰り返しています。

キューのエラーメッセージに ActiveRecord という文字列が見えたので原因がわかりました。
PostgreSQL のマイグレーションをしていなかったのです。

Ver1.2 がリリースされましたが、この版では DB マイグレーションを要求しています。
Docker コンテナの入れ替えを行ったら起動前にマイグレーションコマンドを実行しましょう。

```
 # docker-compose run --rm web rails db:migrate
```

新しいバージョンというと `public/assets/` のファイルもおそらく更新されていると思います。アセットコンパイルも忘れずに。(UI リソースをいじっている場合は上書きに注意)

```
 # docker-compose run --rm web rails assets:precompile
```