サーバー周りをAWSで固めてmastodonインスタンスを立てたので、その手順と資料をまとめました。
立て終わった後に書いたので、記憶違いなどあるかもしれません。コメント・編集リクエストしてください
なぜAWSなのか
インスタンスが落ちてもお金を突っ込めばスケールできるから。
必要なもの
- ドメイン
- メールを配信する手段
- AWSのアカウント
- docker・Web・Linux・AWSなどについての基本的な知識
構成
- 基本的にはmastodonの公式レポジトリに出てくるdocker-compose.ymlを使うだけ
- 無料SSLを使うためにRoute53とEastic Load Balancerを使う
- Redisを外に出すためにElastic Cacheを使う(Optional)
- Postgresを外に出すためにRDSを使う(Optional)
- メール送信サービスとしてはSendGridを使った
- 本筋とは関係ないので今回は省略
- SMTPが使えればなんでもいい
手順
- 設定ファイルを埋める
- SSL接続を可能にする
- HTTPでのアクセスを禁止する
- RedisとPostgresを外に出す(Optional)
設定ファイルを埋める
まずはEC2のインスタンスを立てましょう。OSはubuntu、インスタンスタイプはmediumでいいと思います。microにすると、CPUだかメモリが足りなくてデプロイがコケます。
Security Groupの設定については、とりあえず80番と22番が任意の場所から接続できるようになってれば良いです。
そしてEC2上で、mastodon本体をcloneしてきます:
$ git clone https://github.com/tootsuite/mastodon.git
公式のREADMEを参考に、mastodonの設定をします。この時、LOCAL_HTTPSについては、falseにしてください。
sudo docker-compose up まで行けたら、EC2インスタンスの80番ポートを3000番ポートにリダイレクトします:
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000
これにて http://yourdomain.com/から、mastodonインスタンスにアクセスできるようになりました!!!!
SSL接続を可能にする
とはいえhttpでログインするのは怖いので、SSLの設定をしましょう。
Elastic Load Balancerの無料SSLを使います。
ELBの作成
Elastic Load Balancerを作ります。
EC2のダッシュボード > ロードバランサー > ロードバランサーの作成から、ロードバランサーを作成します:
-
リスナー
- HTTPSを選んでください
-
証明書の選択
- 「ACMから新しい証明書をリクエスト」で、SSLの証明書を生成する
- 参考: http://dev.classmethod.jp/cloud/aws/acm-available-in-tokyo/
-
セキュリティグループの設定
- 任意のIPアドレスからHTTPSが受けられるようなセキュリティグループを作成して設定する
-
ターゲットグループ
- HTTPとHTTPSの両方を追加する
-
ヘルスチェック
- HTTPで
/aboutにする
- HTTPで
-
ターゲットの登録
- 先ほど作成したEC2のインスタンスを選択する
- ポートは80番を選択する
- 先ほど作成したEC2のインスタンスを選択する
※作成されたELBのarnはメモっておきましょう。
ELBとインスタンスの接続
EC2ダッシュボード > ターゲットグループから、先ほど作成したターゲットグループを選び、「ターゲット」に登録してあるEC2インスタンスの状態がhealthyであることを確認する。
もしunhealthyであれば、ドキュメント等を参考にして解決しましょう。
ドメインとRoute 53を連携する
ドメインをELBで使えるようにします。
Route 53 > HostedZones > Create Hosted ZonesからHostedZonesを作成します。
HostedZoneを作成したら、ドメインのNSをHostedZonesのNSの値で置き換えます(参考: お名前.comのドメインをAWSで使用する4つの方法
)。
そして、Create Record Setから、Type AのRecord Setを作成します。この時、ALIASをYesにして、Alias Targetを先ほどのELBのarnに設定します。
Congrats!
ここまでの手順で、https://yourdomain.comから自分のmastodonインスタンスにアクセスできるようになったはずです!やったね!
もし繋がらなかった場合は、ELBのセキュリティグループやターゲットグループの設定を見直してみてください。
最終的な状態では、
- ELBにはHTTPSかHTTPでアクセスできる
- ELBのリスナーに80番ポートと443番ポートが設定されている
- ELBに入ってきたHTTPSまたはHTTPのアクセスは、EC2の80番ポートに転送される
- ターゲットグループの「ターゲット」のEC2インスタンスの「ポート」の欄が80である
- EC2のインスタンスは80番ポートでアクセスを受ける
- 以上を妨げないようなセキュリティグループの設定である
- ELBとEC2やその他のAWSのサービスが、すべて別のセキュリティグループを持つ
が満たされているはずです。
HTTPでのアクセスを禁止する
前節まででSSLでのアクセスが実現されましたが、依然HTTPでのアクセスも可能です。
EC2インスタンスへのアクセスがELB経由で行われるようにし、また、HTTPでアクセスされたときはHTTPSにリダイレクトするようにしましょう。
まず、EC2インスタンスのセキュリティグループのインバウンドルールについて、HTTPの行の「送信元」の欄に、ELBのセキュリティグループのID(sg-********)を入力して保存します。
これによって、ELBからのみEC2インスタンスにHTTPSでアクセスできるようになりました。
次に、EC2インスタンスの中で、以下のような設定ファイルでnginxを起動します:
server {
listen 80;
location / {
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
}
}
これにより、HTTPアクセスをHTTPS付きのURLにリダイレクトすることができます。
RedisとPostgresを外に出す(Optional)
前節までで、所望のmastodonインスタンスが手に入ったと思います。
この構成では、中央のEC2インスタンスの中で、Rails・Redis・Postgres・Sidekiq・nodejsの5つのDockerコンテナが動いていることになり、負荷が集中しています。
ところで、AWSはRedis専用のインスンタンスを提供していますし(ElasticCache)、postgres専用のインスタンス(RDS)も提供しています。
実際どのぐらい効果があるのかわかりませんが、これらのコンテナを中央のEC2から切り離してみましょう。
この辺からは適当です。
インスタンスを立てる
PostgresとRedisのインスタンスを立てます。
このとき、Postgresの設定は、mastodonのレポジトリ内の設定ファイル(.env.production)のDB_*変数に合わせて適当に変えましょう。
DB_HOSTの値は後で取得します。Redisも同様です。
次に、PostgresとRedisのセキュリティグループを編集して、EC2のインスタンスからアクセスできるように設定します。
「HTTPでのアクセスを禁止する」の節と同じ要領でできます。
Postgresのインスタンスタイプについてですが、無料枠に収まるようにmicroにしましたが、ちゃんと動いてるようです。Redisのインスタンスは、無料枠が無いようなので、適当にmicroにしました。今のところ大丈夫そうです。
PostgresとRedisのEndpointをメモっておきます
.env.productionを編集
.env.productionのREDIS_HOSTとDB_HOSTを、先程メモったEndpointに書き換えます。
docker-compose.ymlを編集
mastodonのdocker-compose.ymlを修正して、dbコンテナとredisコンテナの部分をコメントアウトしましょう。また、他のコンテナのdepend_onの部分もそれに合わせてコメントアウトします。
再起動
$ sudo docker-compose build
$ sudo docker-compose up -d
にてmastodonを再起動します。
これによって、RedisとPostgresがAWSのサービスを利用する形で切り出されたことになります。
その他
- 運営ガイドがあった: https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Administration-guide.md
- 実際のところ、RedisとかPostgresを外に出したほうがパフォーマンスは出るのか、あるいは料金は安く抑えられるのか、というところは検証したい(誰か検証してほしい)。
- Sidekiq, streamingも外に出したほうがいいのか誰か検証してほしい(他力本願)