見出し画像

妖精界通信 (Misskey建ててみた)

皆さんのTwitterは大丈夫ですか??? は分かりません!!!
そんなわけで最近 Misskey というものを知って、大きなサバに入って :custom_emoji: を登録したりしてました。(一番使ってるのはそこじゃないんだけどね)

Misskeyはかなり丁寧にサーバーの建て方が解説してあるので、比較的簡単に自分でサーバーを建てることができます。
昨今の空前のSNS立ち上げブームに乗って(ここに知人のサバのリンクを貼る) 自分もサーバーを建ててみたので、その内容を備忘録的な感じでNoteにしてみようと思います。

faidra史上かつて無いほど有用な記事です。


全体の構成

生体サーバー

できました。

ざっくり解説

  • ユーザーは 「misskey.faidra.net って何??」 っていう質問をその辺にいるDNSのおじさんに問い合わせます

    • するとおじさんは「それはAWS帝国のとあるLBらしいよってグーグルさんが言ってた」って返します

  • 不審に思いながらもユーザーは知らないおじさんについていき、そのロードバランサーにアクセスしに行きます

    • そのロードバランサーはAWS帝国の証明書を持っていたので、ユーザーはほっとをなでおろします

  • そのロードバランサーくんは帝国領内のEC2(仮想マシン)にアクセスします

    • ちなみにEC2は1台しかないのでバランスは取りません。チョロい仕事だぜ

  • EC2の中ではンジンクスなるWebサービスが待ち構えており、Misskey(Web)のデータを取りに行ったり行かなかったりします

    • キャッシュしてたりしてなかったり

  • Misskey(Web)はRedis, Postgres, S3 という保存が得意なやつらをこき使い、MisskeyのWebページを生成します

  • 生成されたWebページはNGINX、ロードバランサーを遡っていき、最終的にユーザーの開くWebページ(Webサービス)になります

    • 画像は前述のS3を直接見たり見なかったりします

やったこと

概要

  • 上の構成図の通り、Docker Composeを使ったパティーンで、Docker Composeを使ったMisskey構築」を参考にしています

  • 実際にやった手順ではなく、もう一度同じことをするならこうする、という内容を書いています

    • なんかミスってたらごめんね

MisskeyのDocker Imageの準備

  • ローカルマシンで↑のページのビルドまで行います

    • ググると設定ファイルの書き換え方がいろいろ出てきますが、そういったサイトは古い情報なことが多いので、基本的には公式を信頼しましょう

      • (実際にはEC2側で起動させるので、このフェイズではymlの設定要らない、はず?)

    • ビルドには大体メモリ2GBぐらい食うらしいです。最初EC2のt2.micro上でやったら爆発しました

  • MisskeyのDocker Imageが美味しく焼き上がってるはずなので、それをEC2からアクセスできるようにします

    • AWSのAmazon ECRにリポジトリを作成します

    • ECRのリポジトリのページにあるログインコマンドを使ってdocker loginします

    • ビルドしたmisskey/webにいい感じのタグを付けてpushします

EC2の準備

  • EC2のページからインスタンスを起動します

    • AMIは Amazon Linux 2023 AMI にしました。まだ情報が少なくてちょっと大変だったわい

    • インスタンスタイプは最初はt2.microにしてましたが、どうやらメモリ1GBではギリギリ足りないらしく、今はt2.smallにしています

  • SSHで接続できるようにします

    • なんかppmファイルのパーミッションとかで詰まってしまった……

      • なんやかんやしたら直りました

  • dockerが動くようにします

    • sudo dnf install docker

    • sudo systemctl start docker

    • sudo systemctl enable docker

  • docker-composeが動くようにします

    • ここを参考にしました

  • gitが使えるようにします

    • sudo dnf install git

  • ECRを読めるようにします

    • IAMにAmazonEC2ContainerRegistryReadOnlyをつけるか、付いてるものを作ってそれに変更すればいいはず

    • もしかするとこっちでもdocker loginが必要かも? (よく分かってない)

Docker Composeの構築・起動

  • いつものサイトに従ってyml系を設定します

    • linksって実は要らない?気がする (消して動いてる)

    • misskeyをビルドするのではなく、ビルド済みのものを使いたいので、

      • webのbuildをコメントアウトします

      • webのimageを ecrにpushしたやつのuri にします

    • default.ymlの一番下にある maxFileSize はデフォだと小さいので、いい感じに大きくするのがオススメ

    • default.ymlのworker/job系の設定を有効化 & 小さめの値に設定したんですが、たぶんしなくても大丈夫

    • docker-compose.ymlのxxx.deploy.resources.limitsにcpusとmemoryの設定を足しておくと夜ぐっすり眠れるようになります

  • 起動!

    • sudo docker-compose run --rm web pnpm run init

    • sudo docker-compose up -d

  • EC2上でcurl localhost:3000して、Misskeyっぽい物体が流れてくれば成功です

  • EC2のセキュリティグループのインバウンドにカスタムTCP 3000 anywhereを追加すれば、EC2のオープンアドレス:3000 でアクセスできるはずです!

    • とりあえずadminアカはアドレスバレないうちに作っときましょう

      • 安全のため、まずは招待制にしておくと良いと思います

    • 動作確認できたらセキュリティグループは戻そうね

      • 本当は自分の作業環境のIPのみ許可とかでやるほうがいい

Log上限の設定

dockerはデフォルトだとLogの制限がなく、放置すると全てを破壊してしまうので、Logサイズに制限を足します

webとか各サービス: # に、以下を追加
  logging:
    driver: json-file
    options:
      max-size: 1m # お好みで
      max-file: '3' # お好みで

NGINXを追加

  • docker-compose.ymlのservicesに以下を追加します

nginx:
  restart: always
  image: nginx:latest
  container_name: nginx
  networks:
    - internal_network
    - external_network
  ports:
    - "80:80"
    - "443:443" # 結局使ってない
  volumes:
    - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
  • misskey/.configフォルダに /nginx.default.conf を作成します

    • .configフォルダはmisskeyに取り込まれるので、本当は別の所のほうが良いけど、ignoreの設定をサボりました

  • nginx.default.confを ここ を参考にしていい感じにします

    • サンプルにはいろいろあるけど、今回の構成なら↓でとりあえず動くはず

# For WebSocket
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    # Change to your upload limit
    client_max_body_size 10m; // デフォルトは1mb

    # Proxy to Node
    location / {
        proxy_pass http://web:3000; # docker-composeならservice名で解決できるし、そうしたほうがよさそう
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_redirect off;

        # For WebSocket
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}
  • 要するに、ポート80と443を受け取って、パスがなんだろうとweb:3000に渡すよ、その時にheaderとかはちょっと設定するよ、という内容

    • Noteでは省いてるけど、キャッシュとかの設定もいい感じにすると良さそう

  • proxy_pass を localhost:3000 にするとなんかダメでした

    • コメントにある通りservice名が良さそう

  • sudo docker-compose up -d すると、(セキュリティグループの設定でインバウンドに含まれてれば) 普通のhttpでアクセスできるはず

  • nginxをdocker-composeに含んだのはなんかおしゃれだからです。

証明書周り

  • AWS氏~~~頼む~~~EC2から普通に使えるようにしちくれ~~~

  • Amazon Certification Manager (ACM)で取った証明書を使うために、ロードバランサーを使った構成にしぶしぶ切り替えます

    • Let's Encryptはなんかbotのインストールが面倒そうだった

    • LBお金かかる……

    • 追記: 現在はCloudFrontを使った構成に切り替えました

      • 記事下部に足しました

      • 編集がめんどくさかったので一応残します

  • AWSでロードバランサーを作成します

    • Application Load Balancerです

    • ターゲットグループを作成します

      • HTTP: 80でアクセスする設定にします

        • ここの設定を間違えてて、めちゃくちゃ長いこと詰まりました……

      • HTTPS: 443のリスナーを作成しforwardに↑のターゲットグループを入れます

      • HTTP: 80のリスナーを作成し、HTTPSにredirectします

  • ヘルスチェックにpingが使われるので、ec2のセキュリティグループのインバウンドでicmpを許可します

  • Amazon Certification Manager (ACM)で証明書を取ります

    • 使いたいアドレス (今回は misskey.faidra.net ) に向けてDNS認証を依頼?します

  • ドメイン管理サービス (自分の場合 Google Domains )に行き、

    • CNAMEを追加し、使いたいサブドメイン (今回は misskey ) に対し、さっき作ったロードバランサーのアドレスを設定します

    • この辺この辺 を参考に、CNAMEを追加して _xxxx.misskey が _xxxx.xxxx.acm-validatians.aws 的なところに行くようにします

    • よく分かってないけど意外とすんなり行きました

オブジェクトストレージの設定

  • 画像とかを全部EC2に乗せてると多分爆発するので、S3というストレージサービスに逃す設定にします

  • まずはS3をポチポチして作成します

    • 警告されようが無視してパブリックアクセスできるようにします

  • 実際にファイルをダウンロードできるように、バケットポリシーにGetObjectを許可する設定を追記します

 {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::misskey.faidra.net/*"
        }
    ]
 }
  • misskeyからアップロード等するためのアクセストークンを作ります

    • IAMユーザーを作成し、S3FullAccessを足します

    • そいつからアクセスキーを作成します

      • ユースケースはその他にしておいた

  • misskey側でそれを使う設定にします

    • webにadminアカでログインします

    • baseUrlは下に書いてある <bucketid>.s3.xxx みたいな感じではなく、 s3.xxx/<bucketid> 形式で書きます

      • こうしないと違うサブドメインになって証明書のなんたらが発生する & たぶんそのせいでメディアproxyが死ぬ、っぽい?

        • 自分は一応 files というprefixを付けましたが、たぶんなくても大丈夫

    • ↑で作ったアクセスキーとかを設定します

    • ほかもいい感じに設定します

Misskeyの設定

  • コントロールパネルからいろいろいい感じにしましょう

    • サーバー情報はMFMではなくhtmlです

      • <br>や<a href>が使えます

    • サーバーアイコンやテーマカラーはかなり長いこと他のサバにキャッシュされるっぽいので、フォロー撒く前に設定しましょう

      • 私は失敗しました

  • カスタム絵文字を追加しましょう

ヘルスチェックの設定

  • デフォルトだとルートへのping、つまりこの構成ではEC2の死活しかチェックできてないので、実際にmisskeyが生きてるかチェックできるようにします

  • たぶんもっといい方法がありますが……

    • たぶんdocker-composeのhealthを見るのがベスト?

  • Misskeyのエンドポイント一覧 を見ると pingがあった ので、これを使うことにします

  • AWSのターゲットグループがGETでしかヘルスチェックできないので、GET /api/ping を POST /api/ping につなげるproxyを /nginx/default.conf  に追記します

    • (GETするアドレスは特定できれば何でも良いです)

  location /api/ping {
    proxy_pass http://web:3000;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_redirect off;
    proxy_method 'POST';
    proxy_set_header Content-Type 'application/json';
    proxy_set_body '{}';
  }
  • ターゲットグループのヘルスチェックに使うパスを /api/ping にします

  • ついでに、必要回数を2に減らして間隔を300sとかにしました

追記: ロードバランサーからCloudFrontへの変更

  • ロードバランサーはお金がかかるので、無料枠のあるCloudFrontへ変更します

    • 記事の画像を作り直すのが面倒だっただけで、最初からCloudFrontでやる方がいいです

    • 今回の構成では両者の役割はほとんど同じです (証明書を返す口で、ほかは全部EC2に丸投げ)

  • CloudFrontのディストリビューションを作成します

    • オリジンドメインに、使いたいEC2のパブリックアドレスを入れます

      • 一覧には出てくれないのでコピペします

    • 圧縮は念のためNoにしました

    • ビューワープロトコルポリシーはRedirectにしました

    • 許可されたHTTPメソッドは一番多いやつ

    • キャッシュポリシーは念のためCachingDisabled

    • オリジンリクエストポリシーはAllViewerに

      • 結局これが原因かの確証はないんですけど、このあたりの設定がWebSocket(リアルタイムな部分)が動くかに関わってそう

    • 料金クラス(エッジロケーション)はとりあえずアジアが入ってるやつにしましたが、これが最善かは不明です

    • 代替ドメイン名(CNAME)に使いたいドメイン (今回は `misskey.faidra.net`) を入れます

    • CloudFrontと同じリージョンでACMで証明書を発行し、設定します

      • 同じドメインだったらDNS検証用レコードは同じでいいっぽい

    • ほかは特にいじってないはず

  • ドメイン管理画面で、使いたいドメインの向かう先をディストリビューションドメイン名に変更します

    • DNS浸透、結構時間かかるし挙動が厄介ですね……

      • サービスの安定性的には新旧生きたまま移行させたほうがいいんですが、原因の切り分けには旧環境を落としたほうが分かりやすいという……

      • やはりioの接続先の変更は遅い……

  • 使わなくなったロードバランサー (とターゲットグループ) を破壊します

    • アドレスは過去に公開してしまっていて、アクセスされると料金が発生するため

  • 注意?: CloudFrontを使ってから、他サバのノートやリアクションを拾うのが数秒遅くなった気がします。インターネットバトルをする人は注意

おまけ

  • Docker Composeでやったけど、bashスクリプトでやる方が楽かも?

  • 現在、サーバー側のメモリ使用量が徐々に増えていくことがあるようです

    • 謎です。

    • ヤバそうだったらMisskeyのDockerを再起動すれば直ります。運用でカバー

  • DomainもAWS(Route53)で買えばよかったな。まあ特に困ってはないのでいいんですけど

  • Twitter、爆発するなら派手に爆発してほしい。フェードアウトは一番困る

  • あまりにも有用な記事を書いてしまい頭がバグったので、投げ銭できるように有料部分を付けました

    • 有料部分は有用ではないです

ここから先は

445字 / 1画像

¥ 100

この記事が気に入ったらサポートをしてみませんか?