Published on [Permalink]
Reading time: 4 minutes

Can one server speak both Jabber and Matrix?

Yesterday I came home to Jabber — my own XMPP server, ralph@mayer.rocks, passing the compliance suite. But I run more than XMPP. There’s a Matrix homeserver (Synapse) too, with bridges puppeting Signal and WhatsApp into it. It’s a lot of moving parts for “sending messages to people.”

So today’s question was bigger: could a single server do it all? ejabberd is an XMPP server like Prosody — but it also ships an experimental Matrix gateway. If that works, one server could speak Jabber to the XMPP world and federate with Matrix. That would let me retire a whole box.

I paired with Claude again, spun up two throwaway VMs — one running ejabberd, one running YunoHost with Prosody 13 — and started poking.

The moment a message crossed the streams

The headline first, because it genuinely made me grin: an XMPP account sent a direct message to my Matrix account, and it arrived in Element. No bridge, no puppeting — ejabberd’s gateway federated straight to my Matrix server and delivered it. XMPP and Matrix are completely different protocols, and here was a message hopping cleanly from one to the other. That’s the kind of interoperability the open web is supposed to have and mostly doesn’t.

But it was fragile. On the ejabberd that Debian ships, every outbound Matrix message crashed instead. We chased it down to a real bug: Debian builds ejabberd against a newer Erlang (OTP 27) whose new JSON encoder rejects the data format the Matrix gateway produces. On the older Erlang that ejabberd’s own builds bundle (OTP 26), it works fine. Same code, different runtime, completely different outcome.

So that got written up and sent where it belongs:

The verdict: not yet

As much as I wanted the “one server” answer, the honest verdict is not yet. ejabberd’s Matrix gateway is experimental and, on the current Debian/Erlang combo, broken. And for plain XMPP, Prosody 13 is actually ahead — it ships the modern authentication stack (SASL2, Bind2, channel binding) that Debian’s ejabberd can’t currently offer. Replacing Prosody would be a step backward.

So: keep Prosody for XMPP, keep an eye on ejabberd-for-Matrix, and revisit once that bug is fixed upstream. I wrote the whole comparison up as a decision doc so future-me doesn’t have to re-derive it.

Hardening what I already have

Prosody 13 has that shiny modern auth stack — but it isn’t switched on by default in the YunoHost package. Flipping it on made my server advertise SASL2 and channel binding (the mechanism that detects a man-in-the-middle even when they hold a “valid” certificate). Naturally, that went upstream too:

The wall I hit

Here’s the twist. I turned on channel binding… and it still can’t actually be used. Channel binding rides on SCRAM, a way of proving your password without ever sending it to the server. And YunoHost — like a lot of directory-backed setups — can’t do SCRAM. It stores your password as a one-way hash and checks logins with a classic LDAP “bind,” which means the server only ever sees the plaintext (PLAIN, protected by TLS). There’s simply nowhere for the SCRAM secret to live.

That’s not a Prosody problem or an ejabberd problem — it’s baked into how the whole platform stores credentials. So rather than hack around it, I filed a clear, evidence-backed question to the people who can actually fix it:

(There was a request for this back in 2020 that got closed because nobody could explain concretely what was broken. This time it comes with the actual blockers, the actual impact, and three concrete paths forward.)

Four contributions in a day

I didn’t end the day with one server to rule them all. I ended it with two bug reports, a pull request, and a feature request — and a much clearer map of what’s actually possible.

And honestly, that’s the better outcome. The fantasy of collapsing everything onto one box is seductive, but the real win is the open network getting a little sturdier: a Matrix bug that’ll get fixed, an XMPP package that’ll ship modern auth, and a platform question that’s finally stated clearly enough to answer.

That, and a message that crossed from Jabber to Matrix and landed in my pocket. Some days that’s enough.

(The unglamorous footnote: getting here involved locking myself out of a test box more times than I’ll admit, a password only a robot knew, and an SSH agent that kept going to sleep. “Standing up a server” is never just clicking install. It never was.)

Mastodon