
Modern messaging: Running your own XMPP server
Since a years we know, or might suspect, our chats are listend on, our uploaded files are sold for advertising or what purpose ever and the chance our social messengers leak our private data is incredibly high. It is about time to work against this.
Since 3 years the European Commission works on a plan to automatically monitor all chat, email and messenger conversations.12 If this is going to pass, and I strongly hope it will not, the European Union is moving into a direction we know from states suppressing freedom of speech.
I went for setting up my own XMPP server, as this does not have any big resource requirements and still support clustering (for high-availabilty purposes), encryption via OMEMO, file sharing and has support for platforms and operating systems. Also the ecosystem with clients and multiple use cases evolved over the years to provide rock-solid software and solutions for multi-user chats or event audio and video calls.
Info
All steps and settings are bundled in a repository containing Ansible roles: https://codeberg.org/codedge/chat
All code snippets written below work in either Debian os Raspberry Pi OS.
Setting up your own XMPP server
The connection from your client to the XMPP server is encrypted and we need certificates for our server. First thing to do is setting up our domains and point it to the IP - both IPv4 and IPv6 is supported and we can specify both later in our configuration.
I assume the server is going to be run under xmpp.example.com and you all the following domains have been set up.
| Type | Name | Notes |
|---|---|---|
| A | xmpp.example.com | your main xmpp server address |
| A | conference.xmpp.example.com | needed for MUC (Multi User Chat) |
| A | proxy.xmpp.example.com | needed for SOCKS5 proxy support |
| A | pubsub.xmpp.example.com | needed for publish/subscribe support |
| A | upload.xmpp.example.com | needed for file uploads |
| A | stun.xmpp.example.com | needed for audio&video calling |
| A | turn.xmpp.example.com | needed for audio&video calling |
Fill in the IPv6 addresses accordingly.
ejabberd is a robust server software, that is included in most Linux distributions.
Install from Process One repository
I discovered ProcessOne, the company behind ejabberd, also provides a Debian repository.
| |
Install from Github
To get the most recent one, I use the packages offered in their code repository.
Installing version 25.07 just download the asset from the release:
| |
Make sure the fowolling ports are opened in your firewall, taken from ejabberd firewall settings.
- 5222: Jabber/XMPP client connections, plain or STARTTLS
- 5223: Jabber client connections, using the old SSL method
- 5269: Jabber/XMPP incoming server connections
- 5280/5443: HTTP/HTTPS for Web Admin and many more
- 7777: SOCKS5 file transfer proxy
- 3478/5349: STUN+TURN/STUNS+TURNS service
Port 1883, used for MQTT, is also mentioned in the ejabberd docs, but we do not use this in our setup. So this port stays closed.
Depending how you installed ejabberd the config file is either at /etc/ejabberd/conf/ejabberd.yml
or /opt/ejabberd/conf/ejabberd.yml.
General configuration
The configuration is a balance of 70:30 between having a privacy-focused setup for your users and meeting most of the suggestions of the XMPP complicance test. That means, settings that protect the provacy of the users are higher rated despite not passing the test.
Therefore notable privacy and security settings are:
- XMPP over HTTP is disabled (mod_bosh)
- Discover then a user last accessed a server is disabled (mod_last)
- Delete uploaded files on a regular base (see upload config)
- Register account via a web page is disabled (mod_register_web)
- In-band registration can be enabled, default off, captcha secured (mod_register, see registration config)
Info
The configuration file is in YAML format. Keep an eye for indentation.
Let’s start digging into the configuration.
Set the domain of your server
| |
Set the database type
Instead of using the default mnesia type, we opt for sql, better said sqlite.
| |
Generate DH params
Generate a fresh set of params for the DH key exchange. In your terminal run
| |
and link the new file in the ejabberd configuration.
| |
Ensure TLS for server-to-server connections
Use TLS for server-to-server (s2s) connections.
| |
The listners
The listeners aka request_handlers inside the config especially for /admin, /captcha, /upload and /ws are important.
All of them listen on port 5443. Only one request handler is attached to port 5280, the /.well-known/acme-challenge.
| |
ACLs & Access rules
For adminstration of ejabberd we need a user with admin rights and properly set up ACLs and access rules.
There is a separat section for ACLs inside the config in which we set up an admin user name root. The name of the user
is important for later, when we actually create this user.
| |
The access_rules should already be set up, just to confirm that you have a correct entry for the configure action.
| |
Now the new root user needs to be create by running this command on the console.
Watch out to put in the correct domain.
| |
Another user can be registered with the same command.
We set root as the admin user in the config previously. That is how ejabberd knows which user has admin permissions.
Enable file uploads
Enabling file uploads is done with mod_http_upload.
First, create a folder where the uploads should be stored.
| |
Now update the ejabberd configuration like this:
| |
The allowed file upload size is defined in the max_size param and is set to 10MB.
Make sure, to delete uploaded files in a reasonable amount of time via cronjob. This is an example of a cronjob, that deletes files that are older than 1 week.
| |
Registration
Registration in ejabberd is done via mod_register
and can be enabled with these entries in the config file:
| |
If you want to enable registration for your server make sure you enable a captcha for it. Otherwise you will get a lot of spam and fake registrations.
ejabberd provides a working captcha script,
that you can copy to your server and link in your configuration. You will need imaggemagick and gstools installed
on you system. In the ejabberd.yml config file
Add TLS
ejabberd can provision TLS certificates on its own. No need to install certbot. To not expose ejabberd directly to
the internet, nginx is put in front of the XMPP server. Instead of using nginx, every other web server (caddy, …)
or proxy can be used as well.
Here is a sample config for nginx:
| |
Alternative connection methods
The nginx vhosts offers files, host-meta and host-meta.json, for indicating which other connection methods (BOSH, WS) your server offers. The details can be read in XEP-0156 extension.
Opposite to the examples in the XEP, there is no BOSH, but only a websocket connection our server offers. The BOSH part is removed from the config file.
host-meta
| |
host-meta.json
| |
Put that file in a folder your nginx serves. Have a look at the path and URL it is expected to be, see .well-known.
Choose your client
Clients I can recommend are Profanity, an easy to use command-line client, and Monal for MacOS and iOS. A good overview of client can be found on the offical XMPP website.
Citizen-led initiative collecting information about Chat Controle https://fightchatcontrol.eu ↩︎
Explanation by Patrick Breyer, former member of the European Parliament https://www.patrick-breyer.de/en/posts/chat-control/ ↩︎