ここ2年ほど自分用のMisskeyサーバを運用していて、いろいろ構成を変えたりツールの練習台にして楽しんでいる。これまで各所で断片的に「うちはこうしてる」みたいな書き込みはしてきたが、全体像は自分でもまとめたことがなかったので作ってみることにした。
Misskey自体は、自宅サーバ(BMAX B4 Plus)に入れたProxmoxにDebianのLXCコンテナを立ててその上で稼働している。PostgreSQLとRedisも同じコンテナ上にある。コンテナと言ってもDockerとは違ってOS丸ごと仮想化されているので、SSHでシェルに繋いだりsystemdのサービスを作ったりと普通のLinuxマシンと同じように使えて便利。コンテナに割り当てるメモリは4GBあればとりあえず足りる様子。
また、自宅の回線はいわゆるIPv6 IPoE(フレッツ光クロス+v6プラス)なので自由に使えるグローバルIPv4アドレスがない。このためインターネットからの接続はいったんCloudFront+EC2で受けて、Tailscale経由で自宅にReverse Proxyする構成としている。以前はCloudflare Tunnelを使っていたが、不定期に接続できなくなることがあるのと、自宅回線とCloudflare間の経路がおかしくなって通信品質が大きく低下するトラブルがあって対応に難儀したので現状の構成になった。CloudFrontでSSL終端していてそれより後ろはHTTPで流れているが、AWSとTailscaleの上なので大丈夫だろうということにしている。
TailscaleはIPv6に対応しているので、参加しているノード同士、今回で言えば自宅サーバのLXCコンテナとEC2インスタンスにインターネットに到達可能なIPv6アドレスを持たせるとノード間の通信がIPv6で行われる。自宅については上流からDHCPv6-PDで/56が配られるので、LXCコンテナの設定でIPv6 SLAACを有効にしてIPv6アドレスを自動設定させればOKだった。EC2インスタンスは、VPCにIPv6 CIDRを割り当てた上でEC2インスタンスのIPv6自動割り当てをオン。このままだとインターネットに出られないのでEgress-Only Internet Gatewayも作ってVPCに割り当てる必要があった。Ingressはなくても動くのでNAT Gatewayは立てなくてもよい。
↓IPv6アドレスでdirect接続しているの図(クリックで拡大)
Misskeyドライブのファイルは、サーバのディスクを圧迫したくない & サーバーを移転することになったときのファイルコピーがめんどくさそうという理由で当初からオブジェクトストレージに置くようにしている。先述したようにかつてはCloudflare Tunnelを使っていたので、オブジェクトストレージもCloudflare R2を選択した。今ならCloudfront + S3に寄せてもよいのだが、R2のほうがストレージ料金が安いのでそのままになっている。
自宅サーバはいつ壊れてもおかしくないので日次でDBのバックアップを取っている。psqlコマンドでフルダンプを取ってAWS CLIでS3互換のストレージ(Backblaze B2)にアップロードするスクリプトを書いて、systemdのタイマーで毎日実行する素朴な仕組み。いまのところ1回のバックアップで作成されるファイルの容量は100MB程度。ストレージ側でファイルの世代管理ができるのを利用して、最新8世代=1週間分だけが残るようにして保存容量が無限に増えていかないようにすることもできている。
Backblaze B2は容量単価が非常に安いのが魅力で、もともと自宅NASのバックアップに使っていたこともありMisskeyのバックアップもここに置くことにした次第。残念ながらB2からファイルを配信するような仕組みはないので、Misskeyドライブのオブジェクトストレージに使うことはできないはず。
misskey_backup.sh
----
#!/bin/bash
set -xe
# backup db
pg_dump misskey01 > misskey01.sql
# copy to b2
export AWS_ACCESS_KEY_ID=<B2のアクセスキー>
export AWS_SECRET_ACCESS_KEY=<B2のシークレット>
aws s3 cp --endpoint-url=https://s3.us-west-001.backblazeb2.com misskey01.sql s3://<B2のバケット名>/db/misskey01.sql
# remove backup file
rm misskey01.sql
misskey-backup.service
----
[Unit]
Description=Backup Misskey database
[Service]
Type=oneshot
User=misskey
ExecStart=/home/misskey/misskey_backup.sh
WorkingDirectory=/home/misskey/misskey
TimeoutSec=60
misskey-backup.timer
----
[Unit]
Description=Backup Misskey database daily
[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true
[Install]
WantedBy=timers.target
バックアップファイルのサイズは少しずつ増えている
死活監視はuptime-kuma、インスタンスのメトリクスとアプリケーションログの収集はNew Relicを使っている。
uptime-kumaはdockerコマンド1発でいい感じのステータスページが使えてとても便利。こいつは自宅サーバで動かすと何かあったときに共倒れしてしまうので、GCEの無料枠で1番ショボいインスタンス(f1-micro)を立てて動かしている。無料枠の制限で東京リージョンが使えないので日本国内からだとレイテンシーが高めになるが、四六時中見るページではないので問題ない。ステータスは https://status.room4.dev/status/misskey で公開していて、何か問題が起きるとSlackに通知が来るようにしている。
New Relicはsystemdで動いているサービスのログを送ることができるので、Misskeyのログを全部送っている。アクセスログではなくアプリケーションログなので通常はほとんど使わないのだが、Misskeyのアップデートでミスって動かなくなったときに見に行くとエラーログがすぐ見つけられて便利だったりする。journalctlで頑張ってログを読まなくてよいのは非常に楽。
↓Node.jsのバージョン違いで怒られている図(クリックで拡大)
(力尽きたので後で追記するかもしれない)
Cloudfrontの標準ログをS3に送って、Athenaでクエリできるようにしてある。クエリ出来るようにしただけで特に活用はできていない。プライベートのAWS環境にもAWS Organizationsを導入している関係でAWSアカウントを跨いでログを送る構成にしたのだが、ドキュメントの情報があちこちに散らばっていてちゃんと動かせるようになるまで時間がかかった。結局マネジメントコンソールからは設定できなくてAWS CLI叩いたし。
やってる本人が楽しいからこんなことになってるけど、こんなにあれもこれも組み合わせなくてもMisskeyのサーバは立てられるので気軽にチャレンジしてみたら良いと思います。
トップに戻る