最近はあんまりTwitterを見ておらずMastodonにいる。もともと某サーバにいたけれど水が合わないと感じていて、せっかくならおひとりさまインスタンスを持っておくといいだろうなと思い、建立することにした。
立てる前にMasto.hostやHostdonなどのマネージドおひとりさまインスタンス建立サービスも眺めてみたが、運用で遊べる方がいいという気持ちが勝った。どうせやるなら面白そうなほうがいい。あと単純にActivityPubの勉強用途でも使えるんじゃないかという魂胆もある。どうせなんらか遊ぶ過程でMastodonのコードは眺めにいくことになると思う。
というわけで単純におひとりさまインスタンスが欲しいだけであればこれらのマネージドサービスを推す。安いし。ここからは道楽のコーナーです。
構成
普段からAWSにいろいろデプロイして遊んでいるので今回もAWS上に置くことにした。動かすための要件として考えたのは
- 最低限遊べるくらいのスペックのインスタンス
- ただしDBの運用はマネージドに逃がしたい(スナップショットとか勝手に撮ってほしい)
くらい。最初はEC2+RDSを検討していたけど、Amazon LightsailにもマネージドMySQL/PostgreSQLの機能があり、こちらの方が若干安いように見えたのでこれにした。最終的な構成は以下の通り。
- Amazon Lightsail 5ドルプラン
- Amazon Lightsail PostgreSQL 15ドル スタンダードプラン
- 静的ファイル配信用CDNとしてCloudFront + S3
インストール
基本的には Installing from source - Mastodon documentation の手順通りに進めていく。のだが、いろいろとひっかかったので順を追って書いていきたい。といっても手順側は悪くなくて、自分が手順から逸脱しようとして転んだ話。
swap領域を作る
いきなり手順に書いてないことだけど、1GBメモリだとswap領域を作らないと足りないので初手で作っておく。
dd if=/dev/zero of=/swapvol bs=1M count=2048
chmod 600 /swapvol
mkswap /swapvol
swapon /swapvol
echo -e "/swapvol\tswap\tswap\tdefaults\t0\t0" >> /etc/fstab
上から順に実行してあげればswap領域を作ることができる。 swapon -s
で様子を見てあげると丁寧。
Ruby, Node.jsのバージョン
なにごとも最新がいいでしょ、と思って最新版を入れたらやや詰まった。まずRubyについては.ruby-versionでバージョンが固定されているので手順通りのバージョンを指定しないと動かない。
Node.jsについては16が指定されているが18を入れても動く。ただしOpenSSLの互換エラーが出る(Ubuntu 20.04 LTSでインストールされるのは1.1.1fなため)ので rake assets:precompile
を走らせる段で NODE_OPTIONS=--openssl-legacy-provider
オプションを追加する必要がある(実際には rake mastodon:setup
が内部で assets:precompile
を実行しているので、ここで NODE_OPTIONS
を足す)。
メモリが少ないため rake assets:precompile
が落ちる
Node.jsのバージョンだけでなく、メモリが少ないだけでも rake assets:precompile
が失敗する。rake mastodon:setup
の実行時にも
The final step is compiling CSS/JS assets.
This may take a while and consume a lot of RAM.
と表示されていて丁寧だね……という気持ちになる*1。具体的にはヒープ領域が足りずNode.jsのプロセスがクラッシュする。このような場合は NODE_OPTIONS="--max-old-space-size=2048"
のような形で指定することで回避できる。
つまり、Node.js 18環境かつメモリが少ない場合はsetupの際に以下のコマンドを発行すれば良い。
NODE_OPTIONS="--openssl-legacy-provider --max-old-space-size=2048" RAILS_ENV=production bundle exec rake mastodon:setup
S3にオブジェクトを書き込むことができない
これはややひっかかった。S3 bucketの中身はCloudFront経由で配信するので、bucketの設定でパブリックアクセスをすべてブロックしている。Mastodonの中でS3を操作するのに使っているPaperclipはデフォルトでpublic-readのパーミッションでオブジェクトを作成しにいこうとする。すると403 Forbiddenエラーが返ってきてしまう。回避するためにはMastodonのディレクトリ直下にある .env.production
に S3_PERMISSION=private
という値を追記する。これでオブジェクトを作れるようになる。
実際にどういう通信をしているのかな〜と確認するのに以下のIssueコメントが役に立った。
config/initializers/paperclip.rb
の中で http_wire_trace: true
をオプションとして渡すと通信の様子がログに出てくる。こういうのをproductionにおもむろに差しこんで遊べるのはおひとりさまインスタンスのいいところだと思う。
運用
そんなに難しいことはしていない。ざっくりヘルスチェックと、アップデート戦略を決めるくらい。
Mackerel導入
Ubuntuなので公式の手順に則ってmackerel-agentをインストールしただけ。個人のSlackにmastodonチャンネルを作ってホストがreachableかどうかと、外形監視だけ通知するように仕込んだ。Mastodonのヘルスチェックは /health
にエンドポイントがあるのでこれを利用する。
加えていくつかのミドルウェアのメトリックも取得することにした。PostgreSQLのメトリックも見たいけどなぜか設定してなかったのでこれはあとでやる。
# Plugin for accesslog
[plugin.metrics.accesslog]
command = "mackerel-plugin-accesslog /var/log/nginx/access.log"
# Plugin for Linux
[plugin.metrics.linux]
command = "mackerel-plugin-linux"
# Plugin for Redis
[plugin.metrics.redis]
command = "mackerel-plugin-redis"
# Plugin for Sidekiq
[plugin.metrics.sidekiq]
command = "mackerel-plugin-sidekiq"
詳しくはこちら
mackerel.io
しばらく見ている限りは1GBのメモリだと常時70%-90%くらい使っていて暇がない感じがする。が、まあ普通に動いているので良いでしょうという感じ。だいたい30フォロー/フォロワーの規模感でこれなので、もっと増えたときにどうなるのかは分からない。
アップデート戦略
あんまり凝ったことはせず、ひとまず以下のようにした。
- アップデート情報をキャッチできるようにRSSを購読する
- 週1でアップデートデーを設けて必要だったら更新する
アップデート情報はRSSをSlackに流すようにした。都度SlackのIntegrationを変更するのは面倒なので、一旦大チェッカーで受けて、ひとつのフィードにまとめてからSlackに流すようにしている。
daichkr.hatelabo.jp
アップデートデーはTodoist上で管理していて、週1でリマインドされる。もちろん緊急性の高い更新がやってきた場合はアップデートデーによらず対応するつもりだけど、いまのところはNode.jsの軽微な更新しか来ていない。
引っ越し
もともと別のサーバにいたのでアカウントを引っ越した。MastodonにはActivityPubのMove Activityを利用した引っ越しの仕組みがあって、フォロワー側の実装がこれに対応している場合はそのフォロワーのフォロー先を強制的に新しいインスタンスに向けることができる。misskeyやgotosocial、Wildebeestなどでは現時点では対応しておらず、別途フォローをお願いすることになる。
docs.joinmastodon.org
投稿はエクスポートできるがインポートはできないので注意が必要。
というわけで https://social.masawada.me におります。いまのところ流速がおだやかで平和〜という状態。