Back

<article>



Started: Tues 24 March 2026

Finished: Tues 27 April 2026

Published: Tues 5 May 2026

Never look at Discord Again: XMPP Bridges are good now

There has been discussion lately on chat protocols, unfortunately I am late to this party since the zeitgeist has already move onto uhhhhh

Unfortunately this is not a guide to revolutionary change instant messaging technology and unshackle us from dystopian panopticons with a new decentralized, end to end encrypted, federated, zero trust, community orientated multimedia protocol or whatever people are pushing these days but rather dragging what ultimately is a promise from the past kicking and screaming into the present.

The Promise: Pidgin

What if all the people you knew online could be communicated to with the same interface?

No hopping between your Skype, IRC, AIM…The flower one, just one interface so you can thank you grandma on Skype for the new sweater, talk to your warez friends on IRC, message your normie friends on AIM and get blackmailed on the flower one1 with one application and one interface.

This promise has been kicking around for nearly 30 years2 with Pidgin. Its a traditional desktop app the runs on Linux and Windows, it has “plugins” that contain code to network with various past and present “““protocols”““, ofcouse all written in C and just dlopened in.

I used pidgin for many years and can confirm that it works, quite well. I used its plugins for Whatsapp, Teams and Discord, they weren’t nearly “set and forget”, some features (that I cared about) were not implemented or were jankily so, but it had by far the best user interface of any chat app I’ve yet to use. It was fast, worked well with your GTK(2) theme, and got out of your way.

Better than pidgin is my current baseline for “better” which is already kinda a hard sell. I switched from pidgin just because of the lack of a mobile client and spotty “offline message history”. If you don’t care about those things than just use pidgin honestly.

Also pidgin is still in development nearly 30 years later and is getting a swanky new 3.0 version!

The Protocol: XMPP

XMPP, is only a month or so younger with its existence announced in January of 1999, its first implementation in February 2000 and then standardized in 2004

I should clarify that XMPP is a fully featured protocol in its own right with replies, emoji reactions, chat rooms, video conferencing, encryption, and its own network of servers. XMPP is built to be a replacement to centralized protocols and is an excellent one at that. Unfortunately something something network problem were stuck with TRASH boohoo.

However thanks to this full featuredness, XMPP makes for an excellent inbetween protocol between your legacy one “Discord, Whatsapp, Telegram…” and your client. A major problem with pidgin is that pidgin didn’t support replies, thus all of its plugins that connected to protocols that unsurprisingly did support replies had a fun and bespoke way to show replies, multiply this with every new feature from 2003 and you have J A N K

In Addition XMPP of course works best between XMPP clients, However It does acknowledge programs that might want to connect to legacy protocols strewn across its dozens of standard, leading to some light standardization of them (like the name legacy protocol!). XMPP being the eXtensible Messaging and Presence Protocol is also well suited for integrating these programs.

Enter Slidge & Prosody

Slidge the new bridge program for XMPP, like all good things its a python program advertising itself as beta-grade software but were rolling with it anyways.

Prosody is a XMPP server written in Lua. There are alternatives, such as ejabberd written in Erlang and Openfire written in Java however Prosody seems to be the easiest to setup and geared more towards hobbyist installations.

Installation Guide

Since XMPP is a networked protocol it requires you to run the server somewhere. XMPP takes hilariously little resources so the cheapest plan of your VPS provider should suffice, unlike some other protocols ahem Matrix.

  1. First you install prosody, if your on linux it should already be in your repo.

  2. Second you install slidge, unfortunately slidge isn’t in most repos, however there is a debian package. Failing that your should be able to just

pipx install slidcord

According to their documentation. Since I installed it using the debian packages I’ll assume you have too.

  1. Write the prosody configuration file

There should be an example configuration file at /etc/prosody/prosody.cfg.lua. You can largely follow the configuration guide however I’ve included some sections which need to be added to get slidge working. You can also take some shortcuts if running locally

admins = {"admin@inside"}
#...
http_files_dir="/var/lib/slidge/attachments"
http_interfaces = { "127.0.0.1" }
http_ports = { 5280 }
http_default_host="inside"

modules_enabled = {
    #...
    "privilege";
    "http_files";
    #...
}

privileged_entities = {
    ["discord.inside"] = {
        roster="both";
        message="outgoing";
        iq = {
            ["http://jabber.org/protocol/pubsub"] = "both";
            ["http://jabber.org/protocol/pubsub#owner"] = "both";
            ["urn:xmpp:http:upload:0"] = "get";
        }
    },
    #... <repeat for each service>

VirtualHost "inside"

Component "discord.inside"
    component_secret = "<your secret>"
    modules_enabled = {"privilege"}

}
  1. Create your prosody admin

$ prosodyctl adduser admin@inside

Since we already specified that username as an admin in /etc/prosody/prosody.cfg.lua it should have admin privileges. Otherwise you can use prosodyctl shell user set_role admin@inside prosody:admin

  1. Then configure slidge, there should be a /etc/slidge containing example files something like:
../
./
conf.d/
common.conf
discord.conf.example
facebook.conf.example
matrix.conf.example
mattermost.conf.example
...

Copy the files of the services removing the .example ending and edit them. Do not be deceived by conf.d or common.conf as they don’t work in my experience.

  1. Edit the files
user-jid-validator=.*@inside
admins=admin@inside
secret=<your random secret>
jid=discord.inside
legacy-module=slidge.plugins.discord
mam-max-days=30
no-upload-path=/var/lib/slidge/attachments
no-upload-url-prefix=http://127.0.0.1:5280/files/

You can have multiple slidge files, which means you can have multiple bridges running at the same time. You just need to add a corresponding component section in your prosody config for each service. I have 2 discord bridges running at the same time for two different accounts and a whatsapp bridge

Different bridges have specific config options, such as the whatsapp bridge having add-group-participants-to-roster. The discord bridge configuration options. You can also find the portal for all the bridges.

Unfortunately the slidge documentation urls are not cool urls and are kinda hard to navigate with search engines

  1. Start the services
systemctl start slidge@discord
systemctl start slidge@<name of config file without .conf or path>
systemctl start prosody

You can also monitor them at

systemctl status slidge@discord
journalctl -r -xeu slidge@discord
...
systemctl status prosody
  1. Install an XMPP client

There are a few XMPP clients

XMPP being an open standard means there’s a range of clients to choose from, similar to how there’s a gorillion different email clients for every technology and platform under the sun (and yet everybody just uses gmail/outlook web interface uGH). However the clients are arguably XMPP’s biggest stumbling block as they each contain small papercuts and small (depending on who you ask) interoperability problems.

Some of this is a consequence of design, being eXtensible, the only “Core” functionalities are the RFCs which are more “plumbing” to send messages and those “offline/busy/online” indicators5 rather than a modern chat protocol, which comprise the XEPs, which there are a lot of. Good clients should try to implement as many of these as strictly as possible though this is somewhat of an hair tearing task, even if its just glorified mapping of XML snippets onto a UI.

XMPP Clients

Read More: - Dig Deeper’s “Mitigation” of XMPP Clients - HandWiki’s Comparision of XMPP clients - xmpp.org’s List of XMPP clients

Setting Up Slidge

For each service you will have to set it up. At best this will be just entering your username and password, press connect and everything is pulled down into your roster. If you don’t have the privilege extension you will have to manually add every contact you want to talk to over XMPP to your roster by using your clients “Start Chat” function. It should be able to auto-populate this list with your various contacts and group chats so it isn’t too difficult.

However The logging in part because of the Modern Internet™ sometimes involve Copying your account token using the Developer Console or scanning ASCII qr codes with your phone.

Assuming everything went as planned you should see a bot channel for each service (yes even duplicates of the same service) show up in your roster automatically (Add them using the “Start Chat” function their jid’s will be “.”), Type “help” in them and follow the instructions for each service.

Screenshot of an already logged in bridge bot channel

If you are COOL KID, you can use XEP-0004 Data Forms and XEP-0030 Service Discovery to use a GUI to configure your bridge instead of typing in your commands like some IRC huffing uncivilized APE.

Illustration showing how to reach the “Service Discovery” screen of Gajim

An already logged in bridge can also be configured here as well as seeing all your group chats and contacts.

Limitations

I will admit I have a low standard for “working” modern texting. The major thing I want with these XMPP bridges and texting in general is reliable notifications of new messages from individual contacts across devices and quickly sending responses. Such the limitations here does not particularly bother me however It might be a show stopper for others.

Because of these limitations whenever I want to do “serious texting” (like sending an image lmao; but more commonly to check on a server channel I’m too lazy to add to my roster) I boot up the web UI in a different Firefox profile and do whatever I need to. I still have the discord app on my phone from before I set this up but I could probably do without. So the truth is uncovered, this blog post is CLICKBAIT and I AM KILL. Whatever this is why this is at the bottom, attention deficit orange site users will never reach here.

Another major limitation is THE AI SPAM DETECTION OVERLORDS. Connecting to a legacy protocol in this manner is usually against the Terms of Service of most major platforms, especially Discord, who’s spam detection software has a specific hate boner against this sort of thing. This was a major issue with Pidgin, but mostly because It would keep fetching multiple messages at once from the past instead of as they come in. Adding a channel from a busy was also bound to get you instabanned because of the many messages being pulled. An XMPP bridge has the benefit of running all the time so only pulling in messages as they come in.

The best way to quell the AI SPAM DETECTION OVERLORD is to have your server on the same IP you normally access the legacy platform over. If you have your server running on a different machine like a VPS access your legacy protocol’s web UI over a proxy to your VPS regularly to train it as the “main” IP. Do the same but with Android VPNs making sure the mobile app always connects through the IP aswell though I don’t know the necessity of doing this. I will probably write a later blog post about doing this as part of using VPNs to secure servers.

The Future? and Beeper

I tried Beeper a few months ago when getting fed up because of an issue with my XMPP setup (I hadn’t configured image supported correctly). Funnily enough it is also based on XMPP but has its own proprietary secret sauce bridge programs, I believe you are able to connect to beeper using a regular XMPP client however this was under a special advanced option so I wouldn’t count on it. Its first party “app” is very nice and reminds me of Telegram’s.

Its a paid service with a free tier limiting you to like 3 accounts, being a paid service I expect the feature set and reliability to exceed this free-as-in-freedom setup by a wide margin, Tho I didn’t get the time to really run it through its paces.

Ultimately bridging to legacy protocols is just a band-aid, as at any time they could radically change it, implementing FaceID-Device Attestation-Retinal Scan-Anus Topology-Age Verification DRM technology just to send a request. This also doesn’t help that the person on the other end is injecting the full octane experience straight into their retinas and neural pathways, or that this doesn’t effect the culture.

It is also important to note that texting is largely useless, Instant messaging is vastly overrated. I probably would not recommend doing such a complicated setup for yourself as Instant Messaging is probably not worth the all the engineering that has gone into it. I admire it and at one point thought it necessary thus creating this setup but hearing the inane drivel and the lame injokes of the average Group Chat or Server user has dismayed me. Most people on the internet is boring and If you do find an interesting person you could instead E-Mail them for no appreciable difference but an improved experience for the both of you.

For the purposes of sending “where the hell are you we were supposed to meet 10 minutes ago” SMS was all we needed. If legacy protocols and “communities” like Discord die then nothing of value is lost.

This is, very flexible, probably too flexible, turning into a bit of a pain. Gajim instead treats groups as tags, like gmail treats folders as tags. Additionally Gajim mixes all your accounts contacts into the sidebar where their organized by most recent activity. You may like it or hate it, Psi+ perserves the more traditional tree model. A brief wiki entry on it


  1. A very cool miniseries called “Welcome to the Scene”↩︎

  2. Pidgin (Gaim as it was known at the time) released in 1998↩︎

  3. https://xkcd.com/1782/↩︎

  4. Components are subprograms that integrate into XMPP naturally extending it. However XMPP is called “eXtensible” because of how it can add a (now) huge range of new standardized features over time. This is what has kept XMPP upto “Modern Texting” where the other protocols form the same era are too limiting for popular use today.↩︎

  5. In XMPP land this is called presence↩︎

  6. Your roster can have labeled groups, so you can have your Work group and your Family group with different contacts. Groups can also be nested inside each other infinitely and arbitrarily. So you can have your Family, then Extended Family, then Extended Family I Like groups with contacts in all of them, and contacts can be in multiple and any groups.↩︎

  7. To my suprise XEP-0461 is still marked as “experimental”↩︎