AWSの無料SSLを使ってmastodonインスタンスを立てる手順

  • 61
    Like
  • 4
    Comment

サーバー周りをAWSで固めてmastodonインスタンスを立てたので、その手順と資料をまとめました。

SSLは無料で使えますが、サーバーの使用料とかは普通にかかります。とはいえ、お1人〜10人鯖ぐらいならEC2のmicroでも動かせるので、そんなにお金はかからなそう。
立て終わった後に書いたので、記憶違いなどあるかもしれません。コメント・編集リクエストしてください :pray:

なぜAWSなのか

人数が少ないときは安く済ませられるし、リソースが足りなくなってもお金を突っ込めばスケールできるから(要出典)。

必要なもの

  • ドメイン
  • メールを配信する手段
  • AWSのアカウント
  • docker・Web・Linux・AWSなどについての基本的な知識

構成

  • mastodonの公式レポジトリに出てくるdocker-compose.ymlを使う
  • 無料SSLを使うためにRoute53とEastic Load Balancerを使う
  • Redisを外に出すためにElastic Cacheを使う(Optional)
  • Postgresを外に出すためにRDSを使う(Optional)
  • メール送信サービスとしてはSendGridを使った
    • 本筋とは関係ないので今回は省略
    • SMTPが使えればなんでもいい

手順

  1. 設定ファイルを埋める
  2. SSL接続を可能にする
  3. HTTPでのアクセスを禁止する
  4. 画像や動画などをS3に保存するようにする
  5. 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の両方を選んでください
  • 証明書の選択
  • セキュリティグループの設定
    • 任意のIPアドレスからHTTPSが受けられるようなセキュリティグループを作成して設定する
  • ターゲットグループ
    • HTTPだけを追加する
  • ヘルスチェック
    • HTTPで/aboutにする
  • ターゲットの登録
    • 先ほど作成したEC2のインスタンスを選択する
      • ポートは80番を選択する

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