Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

サーバー周りを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も外に出したほうがいいのか誰か検証してほしい(他力本願)
  • 結局インスタンスは人が集まらなかったので閉鎖した。アカウント作ってくれた人ごめんなさい。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away