サーバー周りをAWSで固めてmastodonインスタンスを立てたので、その手順と資料をまとめました。
SSLは無料で使えますが、サーバーの使用料とかは普通にかかります。とはいえ、お1人〜10人鯖ぐらいならEC2のmicroでも動かせるので、そんなにお金はかからなそう。
立て終わった後に書いたので、記憶違いなどあるかもしれません。コメント・編集リクエストしてください ![]()
なぜ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でのアクセスを禁止する
- 画像や動画などをS3に保存するようにする
- RedisとPostgresを外に出す(Optional)
設定ファイルを埋める
まずはEC2のインスタンスを立てましょう。OSはubuntu、インスタンスタイプはmediumでいいと思います。microにすると、CPUだかメモリが足りなくてAssetsのコンパイルでコケます。
しかし、サーバー自体はmicroでもそこそこ快適に動くので、デプロイが終わったらmicroにしましょう。
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とHTTPの両方を選んでください
-
証明書の選択
- 「ACMから新しい証明書をリクエスト」で、SSLの証明書を生成する
- 参考: [AWS Certificate Manager]東京でも無料でSSL証明書が使用可能になりました! | Developers.IO
-
セキュリティグループの設定
- 任意のIPアドレスからHTTPSが受けられるようなセキュリティグループを作成して設定する
-
ターゲットグループ
- HTTPだけを追加する
-
ヘルスチェック
- 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にリダイレクトすることができます。
画像や動画などをS3に保存するようにする
この状態だと、アップロードされた画像・動画やユーザーのアイコン画像は、すべてdockerコンテナの中に保存されます。
そのため、sudo docker-compose downするたびに、画像と動画が消えてしまうし、アイコン画像もなくなってしまいます。
これではうまくないので、メディアファイルのストレージをS3に設定しましょう。
まず、S3のバケットを作成します。バケットの名前とリージョンは覚えておきましょう。
次に、AWSのIAMコンソールからユーザーを作成して、アクセスキーを取得します。このとき、既存のポリシーを直接アタッチから、AmazonS3FullAccessを追加しておきましょう。
そして、.env.production.sampleのコメントアウトしてある設定を利用して、以下のように設定を書き加えます:
S3_ENABLED=true
S3_BUCKET=${your-bucket-name}
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
S3_REGION=${your-bucket-region}
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のサービスを利用する形で切り出されたことになります。
その他
- 運営ガイドがあった: documentation/Administration-guide.md at master · tootsuite/documentation
- 実際のところ、RedisとかPostgresを外に出したほうがパフォーマンスは出るのか、あるいは料金は安く抑えられるのか、というところは検証したい(誰か検証してほしい)。
- Sidekiq, streamingも外に出したほうがいいのか誰か検証してほしい(他力本願)
- 結局インスタンスは人が集まらなかったので閉鎖した。アカウント作ってくれた人ごめんなさい。