世界を動かす技術を、日本語で。

自分のXMPPサーバーを運営する

概要

  • Prosody をDockerで構築し、 XMPPによる連合型メッセージング を実現した手順まとめ。
  • ファイル共有・音声通話・エンドツーエンド暗号化 に対応。
  • DNS設定・TLS証明書・Docker Compose構成 から詳細に解説。
  • セキュリティやクライアント連携 までカバー。
  • 自己ホスト型メッセージング の実用的な導入事例。

Prosody+Dockerによる自前XMPPサーバー構築メモ

  • Signal 中心の生活から、 自己ホスト型メッセージング への移行経緯。
    • Signalは便利だが 単一事業者依存 のリスク。
    • XMPPは 連合型プロトコル で複数サーバー間の自動連携が可能。
    • サーバーデータは 自分のハードウェア に保存。
    • Monal・Conversations など、近年のクライアントは使いやすさ向上。

前提条件

  • Docker・Docker Compose 導入済みサーバー。
  • 独自ドメイン 保有。
  • TLS証明書 (Let’s Encrypt推奨)。

DNS設定

  • SRVレコード でクライアントや他サーバーからの発見性確保。
    • _xmpp-client._tcp.xmpp.example.com → ポート5222
    • _xmpp-server._tcp.xmpp.example.com → ポート5269
  • Aレコード でxmpp.example.comをサーバーIPへ。
  • ファイルアップロード用 にupload.xmpp.example.com、 グループチャット用 にconference.xmpp.example.comのCNAME/Aレコード推奨。

TLS証明書取得

  • Let’s Encrypt+Cloudflare DNSチャレンジ で自動取得。
    • certbotをDockerで実行、cloudflare.iniにAPIトークン記載。
    • 取得後、 証明書のパーミッション修正 必須。
    • 月次自動更新のcron設定 推奨。

Docker構成例

  • docker-compose.yml
    • prosodyim/prosody:13.0イメージ利用。
    • ポート5222(クライアント用)、5269(連合用)を公開。
    • 設定ファイル・証明書はread-onlyでマウント
    • ボリュームでユーザーデータ・メッセージアーカイブ 保持。

Prosody設定

  • 有効化モジュール例

    • "carbons":全デバイス間のメッセージ同期。
    • "smacks":ストリーム管理で不安定な接続でもメッセージ損失防止。
    • "cloud_notify":プッシュ通知対応。
    • "mam":サーバー側のメッセージ履歴管理。
  • セキュリティ設定

    • c2s/s2s通信の 暗号化必須
    • 自己署名証明書のサーバーは連携拒否 (s2s_secure_auth有効)。
    • 登録無効化 で手動アカウント発行。
  • エンドツーエンド暗号化(OMEMO)

    • サーバー設定不要、 クライアント側で有効化
    • Monal・Conversations・Gajim等が標準サポート。
  • メッセージアーカイブ

    • 1年間保存、アーカイブはデフォルト有効。
  • ファイルアップロード

    • 内部HTTP(5280)で提供、TLS終端は Caddy等のリバースプロキシ で対応。
    • http_external_urlで外部URL指定。
  • 仮想ホスト・コンポーネント設定

    • VirtualHostで証明書指定。
    • conference(MUC)でグループチャット、uploadでファイル共有。
    • ファイルサイズ10MB、保存期間30日制限。

リバースプロキシ設定

  • Caddy例
    • xmpp.example.com { reverse_proxy xmpp:5280 }
    • HTTPS経由でファイルアップロードURLを提供。

アカウント作成

  • コマンドラインから手動発行
    • docker exec -it xmpp prosodyctl adduser ユーザー名@xmpp.example.com

ファイアウォール

  • 必要ポート開放
    • 5222(クライアント)、5269(連合)、80/443(プロキシ用)。

音声・ビデオ通話対応

  • TURN/STUNサーバー(coturn)導入

    • NAT越え通信 に必須。
    • Prosodyと 共有シークレット で連携。
    • Dockerではnetwork_mode: host推奨(ポート転送不可のため)。
    • 必要ポート(3478, 5349, 49152-49200/udp)開放。
  • Prosody設定追加

    • "turn_external"モジュール有効化。
    • VirtualHost内でTURNサーバー情報設定。

推奨クライアント

  • iOS :Monal(オープンソース、プッシュ通知対応)

  • Android :Conversations(定番)

  • デスクトップ :Gajim(Linux/Windows)、Monal(macOS)

  • いずれも OMEMO暗号化・ファイル共有・グループチャット・音声/ビデオ通話 対応。

検証・診断

  • prosodyctl check でDNS・TLS・接続・モジュール設定を自動診断。
  • XMPP Compliance Tester で機能充足率チェック。

総括

  • Docker2コンテナ+リバースプロキシ のみでシンプル運用。
  • ファイル共有・メッセージ履歴・プッシュ通知・グループチャット・音声通話 を網羅。
  • Signalと併用しつつ、 自己ホスト環境の安心感 を確保。
  • Docker環境があれば週末プロジェクトに最適 な実践例。

Hackerたちの意見

ほとんどの連絡先が移行したから、今は日常会話の95%がSignalになってる。数年前にMatrixサーバーを立てたんだけど、何人かは移行してくれたけど、最終的には旦那も使わなくなっちゃった。UIとアプリの使い勝手がめっちゃ悪かったから(彼は視力がすごく悪いから、これは致命的だった)。別の選択肢を探して、結局Telegramに落ち着いた。オープンで使いやすくて、UIも良くて、面白いスタンプや絵文字もたくさんあったから、ほとんどの友達も移行してくれた。Signalには行かなかったのは、いつもエンドツーエンドの暗号化が必要なわけじゃないし、デスクトップとスマホで同じ会話ができるのが重要だったから。残念ながら、運営してるのがちょっと変わった人だから、今は何を使うべきか迷ってる。

Matrixのアクセシビリティについては、Element Xが年々かなり改善されてるよ。

最近、FluffyChat (https://fluffy.chat/) に出会ったんだけど、マトリックスで動いてて、面白いステッカーや絵文字があるよ ;)

Signalは今、デスクトップクライアントに対応してるよね?

TelegramはMatrixやSignalとは真逆の位置にあるから、あんまり代替案とは思えないな。

残念ながら、あのプロジェクトは変わり者が運営してるんだよね。Marlinspike、Acton、または他の誰か?それがどうして重要なの?

これまでに、チャットのバックエンドとしてメールプロトコルを使おうとしたアプリがいくつかあったよね。あれがもっと人気になってたら良かったのに。メッセージングとメールにはかなりの重なりがあるからね。

同じく、数年前にMatrixサーバーを立てたんだ。新しいXMPPとして宣伝されてたから(以前にXMPPをユーザーとして使ったことがあって、ちょっと変わってたから後継プロトコルが必要だと思った)。Matrixで体験したのは、あなたが説明しているひどい体験と同じだったから、古いXMPPを新しく見直してみたら、すごく良くて、ずっと改善されてる。家族全員が自己ホストのejabberdでXMPPを使ってるから、Matrixで話すよりずっと安心して眠れるよ(それに、synapse... federatedの使用は忘れて)。

Telegramは、プライベートグループチャットよりもIRCやDiscordの公開チャットルームに近い感じだね。

Telegramは、俺が参加した瞬間にスパムが来たり、ランダムなグループに追加されたりして、最悪のサービスだと思う。TelegramよりはWhatsAppの方が絶対いいよ。

もう10年近く、いくつかの人のためにejabberdのインスタンスをホスティングしてる。これがほんとにうまくいってて、リソースもほとんど使わないし、メンテナンスもほぼ不要。新しいメジャーリリースに移行する時にちょっと設定をチェックするくらい。ちょうどその頃、SynapseでMatrixサーバーをホスティングしようとしたけど、すぐにやめた。何もしてないのにリソースをめっちゃ消費して、アップグレード後にわけのわからないエラーメッセージが出て動かなくなったから、再起動する代わりに放置して、自分のアカウントでmatrix.orgに移った。

Ejabberdは数人にはちょっとオーバースペックかもね。Prosodyなら15分以内で簡単に設定できるし、新しいリリースに移行しても設定が壊れないよ。

ejabberdを運営してたし、その後しばらくprosodyも使ってた。でも、連絡先が減ってきて、普通の人には設定が簡単じゃなかったから、やめちゃった。家族のために連携チャットサービスを運営するアイデアは素晴らしいと思うけど、データ所有の観点からは悲しい。結局、WhatsApp、Telegram、Signal、Messengerを混ぜて使うことにした。どうしてもどれか一つを使いたくない人がいるからさ。

プロソディを復活させて、Telegram、WhatsApp、Signal用に https://slidge.im/ を設定してみて。ちゃんとした解決策ではないけど、少なくともXMPPクライアントを使い続けられるし、ユーザーが増えればもっと良くなるよね。 ;)

家族のために約2年間Matrixサーバーを運営してるけど、まあ…普通かな。クライアントがひどい。今、iOSの誰も画像を送れないのは、fluffychatのバグが原因。赤ちゃんの写真を共有するためのチャットの意味がなくなっちゃう。Synapseはすごい。ほぼ自分のVPSを占拠してる。いろんなFOSSプロジェクトの部屋に参加するのは楽しいけど、正直言って、みんなlibera.chatに固執してくれたらいいのにって思う。この記事を読んで、どうしてみんなでxmppを捨ててMatrixに移行したのか、プロトコルがまだまだ優れているのに不思議に思った。

XMPPとMatrixの問題は、複雑さがどこにあるかってことだと思う。XMPPは拡張(XEP)に複雑さを持たせてる。コアプロトコルはシンプルだけど、どのXEPをサポートするかを選ばないといけなくて、結果的に断片化が起きる。2つのXMPPクライアントが全く異なる機能セットをサポートすることもある。一方、Matrixはプロトコル自体に複雑さを持たせてる。連携のためのDAGベースのイベントグラフはエレガントだけど、コストがかかる。SynapseがVPSを食いつぶすのは、その設計選択の直接的な結果。各部屋は完全な因果履歴を維持していて、一貫性の保証には良いけど、リソース使用には最悪。スレッド内のejabberdのコメントが示してる通り、「うまく動いて、ほとんどリソースを使わず、ほぼメンテナンス不要」なのが10年近く続いてる。これがXMPPの体験で、トレードオフを受け入れた結果だと思う。Matrixを捨てたのは、技術的に優れていたからじゃなくて、Matrixがちょうどいいタイミングで良いストーリーを持ってきたからだと思う。実際に動くシングルリファレンスクライアント(Element)、明確な仕様(400以上のオプションのXEPじゃなくて)、メールのような連携があったから。皮肉なことに、両方のプロトコルが今同じ存在的な問題に直面してる。連絡先が移行しないってこと。WhatsApp、Signal、iMessageのネットワーク効果が本当の敵で、プロトコルの設計じゃない。

XMPPをみんなで捨てた理由を本当に知りたい。開発に関わっていた人や、近くで見ていた人の話を聞きたいな。編集:どうやら誰かが良い返事をくれたみたい。

20年近く、さまざまなプロフェッショナリズムの状態でXMPPサーバーを運営してきた。お母さんの地下室から、投稿で説明されているようなコロケーションサーバーまで。唯一解決できなかったのは、メールのように別のドメインのxmppサーバーをホスティングすること。例えば、joe.doe@example.ORGのアカウントに接続するクライアントは、SRVを通じて接続したいサーバーを見つけるけど、そのサーバーが「example.ORG」のTLS証明書を持っていない(または簡単に取得できない)ことを期待する。これは多くの点で理にかなってるけど、ホスティングサービスを提供する方法を制限してしまう。もし誰かクリエイティブな解決策があれば、ぜひ教えてほしい。

もちろん、サーバーで提供するドメインには証明書が必要だよ。ACME DNSチャレンジを使えば、簡単に手に入るよ(クライアントには自分のドメインの_acme-challengeサブドメインにCNAMEを設定してもらってる)。

自分のドメインでホスティングできるサービスを少なくとも2つ知ってるよ: https://my.snikket.org/ と https://account.conversations.im/domain/ だから、設定するのはそんなに難しくないと思う。

私はいつも自己署名証明書を使ってる。最初に接続すると、クライアントがユーザーにCAを信頼するかどうか聞いてくるよ。セキュリティの観点では、実際には大差ないんだ。

Snikket ( https://snikket.org/ ) は、XMPPサーバーをセルフホスティングするのに簡単な方法だよ。Dockerイメージにプリコンフィギュアされたプロソディサーバーで、好きなXMPPクライアントと一緒に使える。 > 「私は日常的な会話のほとんどでSignalを使っていて、やめるつもりはないよ。」Signal-XMPPゲートウェイを運用できるよ。 https://slidge.im/ これを使えば、XMPPクライアントからSignalアカウントを使えるようになる。音声通話やビデオ通話のブリッジは今のところできないけど、他の機能はゲートウェイを通して使えるよ。

明らかな注意点だけど、自分のコンピュータ以外でこれを運用するとE2EEが無効になるから気をつけて。

Snikket それについて一度調べたことがあるけど、めっちゃ混乱した。XMPPだけど招待が必要なんだよね?それに、SnikketクライアントはSnikketサーバーでしか動かないのに、実際にはProsodyとConversationsに基づいてるってこと?このプロジェクトのすべてが警報を鳴らしてる感じ。

ejabberdはprosodyよりもセットアップがずっと簡単だよ、特にコンテナ化するとね。正直言って、1つに決める前にいくつかのサーバーをチェックすることを強くおすすめするよ。

うーん、わからないな。唯一の良い解決策は、すべてのメッセージングアプリが同じプロトコルを使うことだと思う。そうすれば、誰でも連絡が取れるようになる。でも今はめちゃくちゃだよね。お互いに簡単にメッセージすら送れない。馬鹿げてる。でも、何を言ってるんだろう?同じ単位ですら合意できないんだから。

唯一の良い解決策は、すべてのメッセージアプリが同じプロトコルを使うことだね。そうすれば誰でも連絡が取れる。まさにそれがXMPPが作られた理由なんだ。誰でも実装できるオープンスタンダード。しばらくはそれがうまくいく可能性があったように見えた。WhatsApp、Google Talk、Cisco Jabber、他にもいくつかはXMPPに基づいてたんだ。残念ながら、結局そうはならなかったけど。

「OMEMOはSignalが使っているのと同じ暗号化に基づいているから、信頼するのには問題ないよ。」OMEMOを信頼しないべきだとは言ってないけど(みんなそれぞれの脅威モデルがあるからね)、OMEMOとSignalには人々がよく思っているほどの類似点は少なくて、いくつか重要な注意点があるよ [0]。 [0] https://soatok.blog/2024/08/04/against-xmppomemo/

ああ、あの自信満々な言葉で書かれたブログ記事が大好き。途中でどれだけ間違った主張があるか気づく代わりに、簡単にフィルタリングできるから… :þ

この投稿には、著者が修正する気がない既知の問題があることに注意してください。著者自身の言葉で(OMEMOの人たちからの確認に対する返答として)、「プロトコルバージョンのことについては後で編集するけど、質問に答えるつもりはない。私のこのレースでの全ては、エバンジェリストたちに消えてもらって、私を放っておいてほしいってことだけ。それだけ。それが私の望み。」と言っています。[不適切な表現の検閲は私のもの] この引用は記事内でCtrl+Fしても見つからないので、スクリーンショットに載っている部分です。彼らがモデレートしたために、OMEMOの貢献者の元の建設的なコメントが省かれています。こちらで見つけられます: https://www.moparisthebest.com/tim-henkes-omemo-response.txt なので、ぜひブログ記事を読んでみてください。ただし、その最終的な目的は偏りのない正確な技術記事ではなかったことを理解しておいてください。

1年前に、伝統的な携帯通信(テキストと通話)を置き換えるためにXMPPに全力投球したんだ。サーバーにはVPSでSnikketを使って、電話からXMPPへのゲートウェイサービスにはjmp.chat、接続にはデータ専用のeSIMを使ってた。私の経験では、この投稿で一番の痛点があまり話題になってないんだけど、それはクライアントの状況なんだ。iOSを使ってるから、MonalとSiskin IMを主なモバイルクライアントとして試して、デスクトップクライアントにはMovim/Dinoを使ってた。これらのツールに対するメンテナの努力には本当に感謝してるけど、MonalとSiskin IMのUXはかなり改善の余地があると思う。WhatsAppやSignalに慣れてると、友達や家族を新しいプラットフォームに誘導するのはかなりの障壁になるよ。iOSクライアントを使ってると、UIのバグや機能不足に頻繁に遭遇したし、通知がモバイルで安定して動作することは一度もなかった。通話やテキストの通知は、アプリが画面に開いてない限り、信頼できるものは得られなかった。これのおかげで、外出中に重要な通話やテキストを見逃すことが多かった。デスクトップでは、Dinoは少なくとも通話やテキストが来たときに通知してくれたけど、通話に応答するのはいつも運次第だった。面白いことに、最も多機能で信頼性の高いクライアントはMovimだった。これは、XMPPクライアントが埋め込まれた多機能フォーラム/ソーシャルネットワークなんだけど。Movimでは、通話やテキストの通知が確実に来て、マイクに接続されたブラウザで簡単に通話に「応答」できた。電話サービスを置き換えようとしているなら、3G/LTEの無線は移動中でも信頼性のある接続を維持するのに非常に寛容だよ。セルタワーを飛び回ってもね。でも、XMPPベースの通話はそうはいかないし、運転中や移動中に会話を続けるのはかなりの遅延や途切れが発生する。重要な通知を何度も見逃した後、結局その試みを諦めたけど、もし再度全力で挑むなら、Movimのインスタンスを自己ホスティングして基本の「クライアント」とすると思う。これが試した中で最も信頼性が高くて使いやすかったから。モバイルでは、AndroidのConversationsが良いと聞いたけど、試す機会がなかった。

そうだね、iOSは確かに弱点だって分かってるよ。Monalは現在、UIの大改修に取り組んでる(そのための助成金ももらってる: https://nlnet.nl/project/Monal-IM-UI/)。CheogramとSnikketの間でも新しいアプリが開発中だよ。ベータ版も出てるけど、まだまだ若い段階で(E2EEが完成するまではSnikketのブランドは使わないつもり)。経験をシェアしてくれてありがとう!

自分のXMPPサーバーを約15年間運営してた。その後、10年くらい前にGoogleのGChatがXMPPから移行したんだ。それ以降、誰ともXMPPで会話したことがない。攻撃面を減らすために、2年ほど前にXMPPデーモンをオフにしたよ。

付け加えておくと、俺には「C」っていうアプリだけでやり取りする友達グループがいるんだ。Cは以下のサービスを指してるよ:

  • SMS
  • Apple iMessage
  • Email
  • IRC
  • Facebook Messenger
  • Telegram
  • Slack
  • Webex Teams
  • Discord
  • Twitter (DM)
  • Signal
  • Whatsapp
  • 特定のPHPBBウェブフォーラム これら全部を把握する代わりに、ほとんど無視してるから、友達から「6ヶ月も連絡取れなかった」って文句言われるんだ。XMPPはこの問題への俺なりの「解決策」だったけど、誰も使ってなかった。