老犬に新しい芸を教える:Forgejo+XMPP
原文は Marius により に公開されました。 このブログを購読する

最近Codebergを離れることにした。代わりに自分でForgejoのインスタンスを運用することにしたのだ。初期セットアップを終えて気づいたのは、自分でホストするforgeは自分で形を作れるforgeだということだった。誰かが「これで十分だろう」と考えた機能セットで我慢する必要はもうない。本当に自分のものにできるし、ずっとGitホストにやってほしいと思っていたことを片っ端から有効にできる。
まず手を付けたのは登録の部分だ。今のForgejoは、他のほぼすべてのforgeと同様、メールアドレスを要求してそこに確認リンクを送りつけてくる。どうやらリンクのクリックがいまだに「向こう側に人間がいる証拠」とみなされているらしい。しかし僕としては、むしろXMPPのJIDでサインアップできるようにしたい。理由は二つある。一つは、リンクを受け取れるメールアドレスなど、とっくに自動スパムにとっての障害ではなくなっており、メール認証の恩恵は思われているほどないこと。もう一つは、XMPPの方が優れたプロトコルであり、どうせならユーザーには最初からメールではなくXMPP経由で来てほしいからだ。
残念ながら、ForgejoにはネイティブなXMPPサポートがない。さらに、Goのshared objectsも使われていない。これがあれば拡張機能をコアからほぼ独立してビルドできるし、この規模のモノリスならそれが大いに理にかなっているはずなのだが。コア自体に手を入れずにプロトコルをきれいに追加できる場所などないのだ。
とはいえ、僕がやりたかったのは本物のJID登録や認証をForgejoの中に実装することではない。それは風車に立ち向かうようなものだ、経験からそう断言できる。これよりずっと軽い変更の試みですら設計議論やユースケースの収集といった官僚的な要件や、その先のどこかでアステリックスの通行証A38まで求められて潰されてきた。だから、まともだが少しばかりイカれた人間なら誰でもやることをやることにした。Forgejoの既存のメール連携をXMPPにブリッジすることにしたのだ。
Switchyardの紹介
Switchyardは、片側でSMTPを、もう片側でXMPPを喋る小さなデーモンだ。メールとXMPPはたまたま同じアドレス形式[email protected]を共有しているため、受取人はそのまま直接マッピングでき、[email protected]宛てのメッセージはJID [email protected]へのチャットとしてそのまま送られる。サービスがSMTP経由で投げてきたメールを受け取り、それぞれをキューのジョブに変換し、ワーカーが常時接続のXMPPコネクション経由で配信する。サーバーに切断されても自動で再接続する。
通常のメールサーバーのようにSMTPで待ち受けるため、Forgejo側はメールを引き渡すのにパッチを当てる必要がない。実際のメールサーバーに向けるときと同じブロックで、mailerエンドポイントとして設定するだけだ。
[mailer]
ENABLED = true
FROM = [email protected]
PROTOCOL = smtp
SMTP_ADDR = 127.0.0.1
SMTP_PORT = 587
USER = forgejo
PASSWD = `change-me`反対側では、短いswitchyard.tomlで、Forgejo側と突き合わせる認証情報、サブミッションポート用の証明書、そしてすべての送信元となる単一のXMPPアカウントを与える。
[redis]
addrs = ["127.0.0.1:6379"]
[smtp]
allowed_ips = ["127.0.0.1/32"]
username = "forgejo"
password = "change-me"
[smtp.tls]
enable = true
cert = "/etc/switchyard/tls/cert.pem"
key = "/etc/switchyard/tls/key.pem"
[xmpp]
server = "xmpp.myhost.tld:5222"
username = "[email protected]"
password = "change-me"これで、サインアップ確認やパスワードリセット、新しいIssueの通知など、本来ならメールで送られるはずのForgejoのあらゆるメッセージが、代わりにユーザーがメール欄に入力したJID宛てにXMPPで届くようになる。SwitchyardはIDNにも対応している。まあ、それは僕の得意分野だからね。 :-)
SMTPではドメインは常にpunycode形式で運ばれるが、XMPPではネイティブなIDNが使われる。そのため通過する途中で受取人ドメインをデコードし、Forgejoで[email protected]として登録したユーザーは、XMPPではuser@マリウス.com宛てに届く。
Forgejoの先へ
この軽量なサービスはForgejo専用ではない。SwitchyardはSMTPサーバーに向けられるものなら何にでも使え、そのソフトウェア自身は何も変わったことに気づかないままXMPPを喋るように変身させる。相手側で唯一調整すべきなのは、HTMLテンプレートの「Email address」フィールドのラベルを「JID」に書き換えることだ。そうすれば何を入れればいいか分かる。Forgejoの場合は小さなテンプレートパッチで済み、自分で簡単に維持できる。アップストリームがほぼ確実に受け入れないであろう完全なXMPP実装を維持し続けるのとは、まったく次元の違う負担だ。
欠点は、これでメールが使えなくなることだ(今のところは!)。ForgejoがSwitchyardと喋るようになると、送られるものはすべてXMPP行きになり、メールアドレスを入力したユーザーには何も届かなくなる。これはすでに修正に取りかかっている。Switchyardがまず宛先ホストがそもそも実際のXMPPサーバーかどうかをチェックし、そうでなければ設定しておいた通常のメールサーバーへフォールバックして転送するようにするのだ。そうすれば、一つのプロトコル(SMTP)で入ってきたものを、利用可能なら優先する方(XMPP)へ振り分け、そうでなければフォールバック(SMTP)へ転送できる。簡単だ。
これがクリーンでエレガントなエンジニアリングか?もちろん違う。間にジョブキューを挟んでSMTPサーバーとXMPPクライアントを直結しただけのもので、動くし、仕事はする。Switchyardによって、本来はアップストリームにあるべきだがほぼ確実にそこには届かない機能を手に入れられる。僕にとってはそれが、もしかしたら美しさコンテストでは勝てるかもしれないが、おそらく一生パッチのまま残り、Forgejoのリリースのたびにマージして維持し続けなければならないようなクリーンな実装よりもずっと重要だ。
注記: この実装は僕自身のGitプラットフォームであるtty.failでまだ徹底的にテストしている最中であり、他者がサインアップできるよう登録はまだ開放していない。いずれかのプロジェクトに貢献したいなどで早期アクセスを希望する場合は、コミュニティチャンネルに参加して声をかけてほしい!
記事をランダムに読む
コメント
ログインしてコメントする