Notice: _filter_block_template_part_area(): "sidebar" is not a supported wp_template_part area value and has been added as "uncategorized". in /home/ntsnews/public_html/wp-includes/functions.php on line 6131

Notice: _filter_block_template_part_area(): "sidebar" is not a supported wp_template_part area value and has been added as "uncategorized". in /home/ntsnews/public_html/wp-includes/functions.php on line 6131
Running My Own XMPP Server - NTS News

Running My Own XMPP Server

Running My Own XMPP Server

“Notes from setting up Prosody in Docker for federated messaging, with file sharing, voice calls, and end-to-end encryption.”

Notes from setting up Prosody in Docker for federated messaging, with file sharing, voice calls, and end-to-end encryption. About a year ago I moved my personal messaging to Signal as part of a broader push to take ownership of my digital life. That went well. Most of my contacts made the switch, and I’m now at roughly 95% Signal for day-to-day conversations. But Signal is still one company running one service.

If they shut down tomorrow or change direction, I’m back to square one. XMPP fixes that. It’s federated, meaning your server talks to other XMPP servers automatically and you’re never locked into a single provider. Your messages live on your hardware. The protocol has been around since 1999 and it’s not going anywhere. I’d tried XMPP years ago and bounced off it, but the clients have come a long way since then.

Monal and Conversations are genuinely nice to use now. This post covers everything I did to get a fully working XMPP server running with Prosody in Docker, from DNS records through to voice calls. XMPP uses SRV records to let clients and other servers find yours. You’ll need these in your DNS: Port 5222 is for client connections, 5269 is for server-to-server federation. You’ll also want an A record pointing xmpp.example.com to your server’s IP.

If you want HTTP file uploads (I’d recommend it), add a CNAME or A record for upload.xmpp.example.com pointing to the same server. Same for conference.xmpp.example.com if you want group chats with a clean subdomain, though Prosody handles this internally either way. Prosody won’t start without certificates. I use Let’s Encrypt with the Cloudflare DNS challenge so I don’t need to expose port 80: Two ports exposed: 5222 for clients, 5269 for federation.

The data volume holds user accounts and message archives. Config and certs are mounted read-only. This is the core of it. I’ll walk through the key sections rather than dumping the whole file. The ones I found matter most for a good mobile experience: carbons syncs messages across all your devices instead of delivering to whichever one happened to be online. smacks (Stream Management) handles flaky connections gracefully, so messages aren’t lost when your phone briefly drops signal.

cloud_notify enables push notifications so mobile clients don’t need a persistent connection, which is essential for battery life. And mam (Message Archive Management) stores history server-side for search and cross-device sync. All connections are encrypted and registration is disabled since I create accounts manually with prosodyctl. I’ve enabled s2s_secure_auth, which means Prosody will reject connections from servers with self-signed or misconfigured certificates.

You’ll lose federation with some poorly configured servers, but if you’re self-hosting for privacy reasons it doesn’t make much sense to relax authentication for other people’s mistakes. TLS encrypts connections in transit, but the server itself can still read your messages. If you’re self-hosting, that means you’re trusting yourself, which is fine. But if other people use your server, or if you just want the belt-and-braces approach, OMEMO adds end-to-end encryption so that not even the server operator can read message content.

OMEMO is built on the same encryption that Signal uses, so I’m comfortable trusting it. There’s nothing to configure on the server side either. OMEMO is handled entirely by the clients. Monal, Conversations, and Gajim all support it, and in most cases it’s enabled by default for new conversations. I’d recommend turning it on for everything and leaving it on. Messages are kept for a year and archiving is on by default.

Clients can opt out per-conversation if they want. Prosody serves HTTP on port 5280 internally. I leave HTTPS to my reverse proxy (Caddy), which handles TLS termination. The http_external_url tells Prosody what URL to hand clients when they upload files. The MUC (Multi-User Chat) component gives you group chats with message history via muc_mam. I restrict room creation to local users so random federated accounts can’t spin up rooms on my server.

The file share component handles image and file uploads. A 10 MB limit and 30-day expiry keeps disk usage under control. Prosody’s HTTP port needs to be reachable from the internet for file uploads to work. I use Caddy: When a client sends an image, Prosody hands it a URL like https://xmpp.example.com/upload/… and the receiving client fetches it over HTTPS. Port 80/443 for the reverse proxy if you haven’t already.

If your server is behind a router, forward 5222 and 5269. Text and file sharing work at this point. Voice and video calls need one more piece: a TURN/STUN server. Without it, clients behind NAT can’t establish direct media connections. I run coturn alongside Prosody. The two share a secret, and Prosody generates temporary credentials for clients automatically. It runs with network_mode: host because TURN needs real network interfaces to handle NAT traversal.

Docker’s port mapping breaks this. Then tell Prosody about it. Add "turn_external" to your modules, and inside the VirtualHost block: On iOS I went with Monal, which is open source and supports all the modern XEPs. Push notifications work well. On Android, Conversations seems to be the go-to. On desktop, Gajim covers Linux and Windows, and Monal has a macOS build. All of them support OMEMO encryption, file sharing, group chats, and voice/video calls.

This checks DNS records, TLS certificates, connectivity, and module configuration. Fix anything it flags. The error messages are genuinely helpful. The XMPP Compliance Tester is worth running too. Mine scored above 90% after getting the config right. The whole setup runs in two small Docker containers and a reverse proxy entry. Prosody, file uploads, message archive, push notifications, group chats, voice calls.

I still use Signal for most day-to-day conversations and I’m not planning to stop. But having my own XMPP server means I’m not entirely dependent on any single service. I can message anyone on any XMPP server, not just people who signed up to the same one. It’s a nice fallback to have. If you’re already running Docker on a server somewhere, it’s a good weekend project.

Summary

This report covers the latest developments in android. The information presented highlights key changes and updates that are relevant to those following this topic.


Original Source: Dmcc.io | Author: "Danny" | Published: February 16, 2026, 1:39 pm

Leave a Reply