妖精界通信 (Misskey建ててみた)
皆さんのTwitterは大丈夫ですか??? 私は分かりません!!!
そんなわけで最近 Misskey というものを知って、大きなサバに入って :custom_emoji: を登録したりしてました。(一番使ってるのはそこじゃないんだけどね)
Misskeyはかなり丁寧にサーバーの建て方が解説してあるので、比較的簡単に自分でサーバーを建てることができます。
昨今の空前のSNS立ち上げブームに乗って(ここに知人のサバのリンクを貼る) 自分もサーバーを建ててみたので、その内容を備忘録的な感じでNoteにしてみようと思います。
faidra史上かつて無いほど有用な記事です。
全体の構成
できました。
ざっくり解説
ユーザーは 「misskey.faidra.net って何??」 っていう質問をその辺にいるDNSのおじさんに問い合わせます
不審に思いながらもユーザーは知らないおじさんについていき、そのロードバランサーにアクセスしに行きます
そのロードバランサーは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からアクセスできるようにします
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 )に行き、
オブジェクトストレージの設定
画像とかを全部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、爆発するなら派手に爆発してほしい。フェードアウトは一番困る
あまりにも有用な記事を書いてしまい頭がバグったので、投げ銭できるように有料部分を付けました
有料部分は有用ではないです
ここから先は
¥ 100
この記事が気に入ったらチップで応援してみませんか?