サーバー周りを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も外に出したほうがいいのか誰か検証してほしい(他力本願)
- 結局インスタンスは人が集まらなかったので閉鎖した。アカウント作ってくれた人ごめんなさい。