AWS環境で、Mastodonを構築する

AWS環境で、いつも私がMastodonを構築する手順を解説していきます。

# 構成
- EC2インスタンス (t2.micro) Ubuntu 18.04 LTS 1台
- Mastodon v3.1.4 (現時点の最新タグ)
- S3バケット 1台 画像保存用
- SendGrid API 1個 メール送信用

# この構成に至った理由
- DBはRDSにしないの？
    - 高いです！
- RedisはElasticCacheにしないの？
    - 高いです！
- 画像はローカルにしないの？
    - ローカルに保存してもいいですが、EC2はそんなにDISKがない + DISK増設すると費用がかかるので、S3に保存します。
      また、将来的に以下のような移行作業をする際において、移行がめんどうそうだという思いもあります。
      1. 画像をEC2インスタンスからS3に移行する場合  
      2. WEBサーバをEC2インスタンスではなく、別の何かに移行する場合  
- メールはローカルから送らないの？
    - AWSからメールを送信するのは結構大変です。また、メールが送れなかった際のPostfixのトラブルシュートは割と地獄なところがあるので、SaaSのSendGridを利用します。
    - 従量課金です。無料枠が存在します。運用したことはなく、構築の経験しかありませんが、今のところ費用が発生したことはありません。

# 前提
- AWS EC2, S3, Ubuntuサーバにおける基本的な理解
- SendGridについての利用
  - わからなければググれば大丈夫です！

## EC2インスタンスを作成する
- セキュリティグループ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124948/9c3e6099-48dc-4264-39cf-fb73e8f7fcf4.png)

EC2インスタンスへの不正アクセス防止のため、セキュリティグループの設定にだけ注意しましょう。

- SSH: 送信元を絞っています。
- HTTP, HTTPS: Let's Encryptの認証に必要となるため、開けておく必要があります。必要になるまで閉めておいても構いません。
- ICMP: 任意

作成が完了したら、SSH接続をしてみましょう。接続ができない場合は、何かがおかしいです :)

- インスタンスにグローバルなIPアドレスは割り当てられている？
- (セキュリティグループでICMPを許可している必要があります) PINGによる疎通ができる？
- VPCを新規設定した場合、その設定は正しいか？ (結構VPCの設定はややこしい)

## EC2インスタンスを設定する
### SWAPを2GB作成する
あとに行うRubyのビルド、およびアセットのコンパイルなどにおいて、メモリ不足で処理が失敗するということが頻発するかと思います。
これはEC2 t2.microという小さなインスタンスを利用しているためです。
一時的にインスンタンスのスケールアップを行ってもいいですが、ここではSWAPを作成して利用します。

```
install -o root -g root -m 0600 /dev/null /swapfile
dd if=/dev/zero of=/swapfile bs=1k count=2048k
mkswap /swapfile
swapon /swapfile
echo "/swapfile       swap    swap    auto      0       0" | tee -a /etc/fstab
```

参考：https://meta.discourse.org/t/create-a-swapfile-for-your-linux-server/13880


swap領域が拡張されていることを確認します。

```
# free -h
              total        used        free      shared  buff/cache   available
Mem:           983M        105M         68M        748K        810M        730M
Swap:          2.0G          0B        2.0G
```

## ドメインを設定する
Mastodonの設定にはドメインの設定が必要です。
ドメインで対象のインスタンスに接続できるよう、Aレコードの設定を行ってください。

## S3を作成、設定する
以下の作業が必要となります。

- S3バケットの作成
- S3にアクセス可能なIAMユーザの作成

以下のブログを参考に設定してみてください。
私は、 "files.mstdn.taro-hida.tk" という名前で作成しました。
[Mastodon の画像などメディアデータをAmazon S3に移行する（非Docker環境）](http://takanory.hatenablog.jp/entry/2017/05/10/070000#S3%E3%83%90%E3%82%B1%E3%83%83%E3%83%88%E3%81%AE%E6%A8%A9%E9%99%90%E8%A8%AD%E5%AE%9A)

## SendGridを設定する
とりあえず、アカウントを作成しておくだけでOKです。
以下手順のためにAPIキーを取得し、利用します。
https://sendgrid.kke.co.jp/blog/?p=7789


## 公式ドキュメントに従い、設定を進める
まずは下記を実施します。
https://docs.joinmastodon.org/admin/prerequisites/
> Install fail2ban so it blocks repeated login attempts

については、AWSのセキュリティグループで管理するため私は実施していません。
ここはその人の好みでいいかと思います。

次に、下記を実施します。
https://docs.joinmastodon.org/admin/install/

一番詰まるのがここかと思います。
私が構築した際のターミナル出力を共有します。よければご参考ください。
https://docs.google.com/document/d/1M7svmw0gT9kZKZlIt2NRoBXSfCPLwIyehROZhL0Dqew/edit?usp=sharing

`RAILS_ENV=production bundle exec rake mastodon:setup`のコマンド発行においては、以下のように入力しています。

```
$ RAILS_ENV=production bundle exec rake mastodon:setup
Your instance is identified by its domain name. Changing it afterward will break things.
Domain name: mstdn.taro-hida.tk

Single user mode disables registrations and redirects the landing page to your public profile.
Do you want to enable single user mode? No

Are you using Docker to run Mastodon? no

PostgreSQL host: /var/run/postgresql
PostgreSQL port: 5432
Name of PostgreSQL database: mastodon_production
Name of PostgreSQL user: mastodon
Password of PostgreSQL user: <- mastodonと入力しています
Database configuration works! 🎆

Redis host: localhost
Redis port: 6379
Redis password: 
Redis configuration works! 🎆

Do you want to store uploaded files on the cloud? yes
Provider Amazon S3
S3 bucket name: files.mstdn.taro-hida.tk
S3 region: ap-northeast-1
S3 hostname: s3-ap-northeast-1.amazonaws.com
S3 access key: <- 前述したS3作成手順において取得した「アクセスキーID」を入力します。
S3 secret key: <- 前述したS3作成手順において取得した「シークレットアクセスキー」を入力します。
Do you want to access the uploaded files from your own domain? no

Do you want to send e-mails from localhost? No

// 下記手順に従い入力していきます。
// https://sendgrid.kke.co.jp/blog/?p=7789

SMTP server: smtp.sendgrid.net
SMTP port: 587
SMTP username: apikey
SMTP password: <- apiキーのシークレットを入力します
SMTP authentication: plain
E-mail address to send e-mails "from": Mastodon <notifications@mstdn.taro-hida.tk>
Send a test e-mail with this configuration right now? Yes
Send test e-mail to: <-送信テストメールを受信するアドレスを指定してください。

This configuration will be written to .env.production
Save configuration? Yes

Now that configuration is saved, the database schema must be loaded.
If the database already exists, this will erase its contents.
Prepare the database now? Yes
Running `RAILS_ENV=production rails db:setup` ...(以下略)
```

nginx周りも設定誤り等によるトラブルが多い印象です。
トラブルシュートのとっかかりとして、以下を確認してみましょう。

- `/var/log/syslog`を確認しましょう。
- `/var/log/nginx/error_log`を確認しましょう。
- `systemctl status nginx`を発行し、確認しましょう。
- `journalctl -xe`を発行してみましょう。

ぐちゃぐちゃになってさっぱりわからん！という場合は、Nginxの設定ファイルを切り戻してみましょう。以下を発行すれば戻ります。

```
unlink /etc/nginx/sites-enabled/mastodon
```
再度以下の行から再開してみてください。

```
cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon
ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon
```

Certbot周りもトラブルが多いです。
エラーメッセージをよく読めば原因が書いてあることが多いので、ちゃんと読みましょう。

ひっかかるポイントとしては、

- Nginxが起動しているとコケます (80番ポートが使えないため)
- ドメインがちゃんと設定できていないとコケます。  
`dig mstdn.taro-hida.tk`等、名前解決を行い、正しくドメインが引けるか確認してみてください。

## なんかよくわからんことになった！
リソースの問題で固まったり、疎通ができなくなったりします。
リソース状況が怪しければ、リソースの確認を行いましょう。

- `top`コマンドでcpu, memory負荷を確認しましょう。
- `vmstat -n 1`コマンドで、リアルタイムの統計情報を確認しましょう。

なんかコケたりうまくいかなければ、とりあえずググるのがいいです。
ググる取っ掛かりとして、このあたりを確認してみましょう。

- `/var/log/syslog`を確認しましょう。
- `/var/log/nginx/error_log`を確認しましょう。
- `systemctl status nginx`を発行してみましょう。
- `systemctl status mastodon-web mastodon-sidekiq mastodon-streaming`を発行してみましょう。

一回試してみてください。

- Nginxを再起動してみましょう。
- `mastodon-web` `mastodon-sidekiq` `mastodon-streaming`を再起動してみましょう。
- PostgreSQLを再起動してみましょう。
- OS再起動を行ってみましょう。

[おなじみのgif](https://github.com/tootsuite/mastodon/blob/master/public/oops.gif?raw=true) が出ているときとかは、祈りながら上記を繰り返すと治った経験があります。

それでも治らない！もうわけがわからない！！

- 悲しいですが、一度サーバを削除して、最初からやり直してみましょう。  
私も今まで構築するにあたり、よくわからなくなって10回近くサーバ作り直した経験があります。
みんなそんな感じじゃないかなと思います。
- 一度休むことも大事です。頭が回らなくなったらサーバを止めて、また明日やりましょう。  
ElasticIP振ってないとIPv4アドレスが変更になるので、そこだけお気をつけください。