ActivityPub RelayというActivityPubリレーサーバをRails 8を使って作った

はじめに

これはRuby Advent Calendarの7日目の記事であり、Fediverse (4) Advent Calendar 2024の二日目の記事です。

qiita.com

adventar.org

先日松江で開催されたRubyWorld Conference 2024でもLTしたActivityPub リレーサーバの話を、より詳細な経緯などを含めて書いていこうと思います。

speakerdeck.com

ActivityPub リレーサーバとは?

ActivityPub リレーサーバは簡単にいうとFediverseのサーバ同士の連合を強化するためのサーバになります。

Fediverseでは互いのサーバにいるユーザーがサーバを超えてフォローしあうことで互いの連合タイムラインに公開投稿が流れるようになります。

サーバを越えたフォローと配送の図

そのため2017年頃のMastodonではサーバを建てたばかりだとフォローしているアカウントがないため、連合タイムラインに外部のサーバの投稿が流れないということが発生していました。

当時の記憶は少しあやふやですが、僕個人の場合はTwitterなどでサーバを建てた人のアカウントを見つけてそれをリモートフォローしてサーバ同士のつながりを増やしていった覚えがあります。

そういった中でMastodonでは v2.5.0からリレーという機能が導入されました。

github.com

このリレー機能では、以下の図のようにサーバAとサーバBがそれぞれ連合していなかった場合でもそれぞれのサーバの投稿をリレーサーバを中継して配送してくれるようになりました。

リレーサーバの配送の仕組みについての図

ActivityPub リレーサーバとはFediverseの連合を強化するためのハブの役割を果たしてくれます。

ただリレーサーバは銀の弾丸ではなくデメリットも存在します。

例えばスペックを抑えた小規模なサーバを運用していた場合、リレーサーバから配送されてくる大量の公開投稿を処理する負荷に耐えられない可能性もあります。
またリレーサーバに参加しているサーバの規模によっては大量の公開投稿がリレーサーバを経由して自分のサーバに流れてくる可能性もありますし、リレーサーバ自体にも負荷がかかります。

なんで作ろうと思ったのか

まずリレーサーバの実装として現在日本でよく知られているものはおそらく以下の二つになります。

github.com

github.com

それぞれCrystalとGoで書かれています。

そのほかにもRustでの実装やNode.jsでの実装などもあります。

git.asonix.dog

github.com

Rubyの実装に関しては現在も開発されているものはなく、最初期にプロトタイプ版として開発されたものがあり、それを運用されている方がお一人いるという状況でした。
またRubyで実装されたリレーサーバのメンテナンスが大変そう(主にRubyRailsのアップデート対応)で、以前にRubyRailsのアップデート対応のPRを投げたりはしていましたが、それ以上のことは僕もできていない状態でした。
特にプロトタイプ版として開発された背景からかテストがなく、実際にサーバを建てて動作確認をしなければならないのも大変でした。

そんな状況だったので「このメンテナンスしにくいのどうにかできないかなぁ」と思い、「現存するRubyの実装を参考にリレーサーバの実装をテストも書きつつやりたいな」と考え始めました。
それがちょうど去年の年末から今年の年始にかけてくらいで、結構熱中してやっていたんですが他のところでリソースが必要になり徐々に熱が引いていきました。

そんなこんなしていた時に今年のRubyWorld ConferenceでMastodonの開発チームのAndy Piperさんが来日されるというのを聴き、「せっかくMastodonの人が来るんだからActivityPubやFediverseの話をしたい!」と思い、やる気が再燃し、リレーサーバの開発を再開しました。

2024.rubyworld-conf.org

またリレーサーバ開発を再開したぐらいにRails 8が登場しました。
これがリレーサーバの開発をより後押ししたところもあります。

rubyonrails.org

というのも

  • 証明書とかNginx使うかとかどうする?とか
  • Redisどうする?データベースどうする?とか
  • デプロイもSSHでサーバ内に入って手動やるか、もしくはDockerfileなどをいい感じにAWSとかでつかうかとか

という感じで、そもそもリレーサーバを建てる&メンテナンスするのが大変だったんですね。
個人的にはより良い感じにリレーサーバも分散が進む方が負荷も分散できると思っていたので、リレーサーバの建てにくさはどうにかできないかなと考えてました。

それがRails 8を使うことで

  • Thrusterでの証明書の自動更新&Nginx建てなくて良い
  • Solid Queueを使うのでRedisが不要になり、本番環境でSQLiteが使えるので良い
  • デプロイはKamal2がよしなにやってくれるので非常に良い

という感じになりそうだったんですよね。

そういった後押しもあり「いっちょやるか」と開発を再開したのが11月の中旬くらいでした。

作ったもの

そんなこんなで作ったものは以下になります。

github.com

Rails 8で入ったKamal2、Thruster、Solid Queueをそのまま使い、ささっと実装しました。

また本番環境のデータベースはSQLiteを採用しました。
リレーサーバの性質上、配送する公開投稿はデータベースに保持する必要はなく、必要なのは参加しているサーバの情報などだったので「SQLiteでも充分そうだ」という判断もあり、採用することにしました。

現状の機能としては

  • Mastodonのリレーをサポート
  • Misskey(とそのフォークなど)のリレーをサポート
  • PleromaやAkkomaなどのActorリレーも部分的にサポート(ただ問題があってドキュメントには書いていない)
  • 参加サーバの管理画面
  • ジョブの管理画面
  • Google Authenticatorなどで使えるOTPをサポート

という感じになっています。

試験的にリレーサーバとして運用した際にはメモリ1GB CPU1コアのスペックが抑え目なサーバでもサクサクと動いていたので中々いい感じでした。 のえるさんのご協力もあり、負荷試験としてFedibirdからの配送も処理できるか確認してみました。
ジョブの管理画面から見ていた感じだと、Fedibirdが参加する前が一時間で1000ジョブとかくらいだったんですが、参加後は大体毎分1000 ~ 2000ジョブ位を処理していて負荷がいい塩梅に増してました。
稀に配送先のサーバへのリクエストが長引き遅延することはありましたが、それでも基本的には即時でジョブを捌き切っていましたし、なおかつサーバ自体も負荷でダウンするということもなかったので良い感じでした。

現状の運用

現在はKAGOYAさんのメモリ1GB、CPU1コア 、ストレージ25GBでリレーサーバを運用しています。
なので月550円くらいでリレーサーバを建てて運用できるので大分お財布にも優しくて助かってますね。

relay.gamelinks007.net

参加サーバも小規模なサーバかお一人様サーバの人に絞っているので負荷の面も心配はなさそうという感じですね 。

今後

一日あたりの配送している公開投稿の数をグラフで表示したりとかもやっていきたいですね。
多分それがあるほうが「このリレーサーバに参加するとどれくらいの負荷が増すんだろう?」というのが確認しやすいと思いますし。

また小規模なリレーサーバを建てやすくなった&かなり安く済みそうというのもあり、リレーサーバを建ててみたい人向けにフォローとかしていきたいですね。
あと個人的には小規模なテーマリレーサーバとして運用する(古の同人関係のサーチエンジン的な感じで)とかもできそうなのでそのあたりもやってみると面白いのではと考えてます。

参考記事など

blog.noellabo.jp

blog.noellabo.jp

blog.yukimochi.jp

joinfediverse.wiki