Important This is not intended to be an installation guide. Just the description of my journey. If you’re actually looking for sane information on how to setup ejabberd, you should maybe look somewhere else. (See bottom of this post for a link to German instructions.)

The journey begins

Recently, I had the urge to set up a messaging server. Actually, I wanted to go with one of the Matrix servers. But “to get started”, I decided to set up ejabberd first.

Why ejabberd? I tried to set up Prosody quite some time ago, probably before The Pandemic hit. I don’t remember it too fondly. I may have gotten better in the meantime.

The process was done on a recently updated Debian Bookworm. I wanted to figure things out by myself as much as possible.

  • First off: Add the necessary DNS records. The Prosody Docs were the first thing I found. I skipped the TLS-only stuff.
  • apt install ejabberd
  • ejabberdctl register <adminuser> <domain> <password>
    • Error message that the domain was not found? huh?
    • nano /etc/ejabberd/ejabberd.yml and add my domain to the hosts lists.
    • Reload or restart the service
    • Repeat the command. Success! Yay!
  • Take a look at the web interface:
    • Log in with the created user. It fails.
    • Append the @domain part, as the user name alone won’t do it. It works. Yay.
    • “Man, I wouldn’t have thought this was gonna be so easy! Hah!”.
    • Little did I know…
  • Use to generate the certificates. See the instructions in their readme.
    • My setup was somewhat more complicated since I am already running a web server on the machine running ejabberd. If I didn’t run a web server there, I could’ve used the built-in acme plugin in ejabberd. Shoot :( I ended up using the automated DNS mode.
    • I naively started with the domains and The latter wouldn’t even be used actively. It was just so I could distinguish the certificate files.
  • I started out installing the certificates in /etc/ejabberd/certs/. However, I was getting warning messages on service startup that the certificates were empty (“… Permission error?”). Upon pondering on this, I decided to put the certificates in /var/lib/ejabberd/certs/. This is the “home” directory of the ejabberd user. Access problems solved. (1)
  • Getting an warning message Invalid certificate in /var/lib/ejabberd/certs/fullchain.pem: at line 57: certificate is signed by unknown CA on server startup. This puzzled me a lot.
    • Line 57 was the line where the actual server certificate started. The lines above were the Let’s Encrypt X1 root and the R3 intermediate. See their docs for details.
    • At this point, I also tried some openssl verify calls on the PEM file itself. But I didn’t know the correct options to use (-CAfile, -CApath, -untrusted???).
  • As an intermediate step, I tried setting the ca_file config value in ejabberd.yml. The warning was gone. Yay.
    • But then I realized I forgot to add some subdomains to the cert. So I added them (reissue, reinstall, restart). Suddenly, the warning was back. :(
    • For my setup, I added the xmpp.<dom>, pubsub.<dom>, conference.<dom> domains, where <dom> is
  • However. I then realized that setting ca_file was properly not a good idea. This would probably prevent me from contacting servers not using Let’s Encrypt. So I removed the setting.
    • specifically, I explicitly set it to ca_file: '/etc/ssl/certs/ca-certificates.crt'. I don’t know yet if this is necessary.
  • Add an exception to the firewall. (ufw allow XMPP).
  • These warnings made me nervous. So I decided to check the actual TLS connection from my PC.
    • I know I could do openssl s_client -starttls xmpp (server). But this didn’t return a certificate.
    • From HTTPS, I know to send the -servername. But this option didn’t help.
    • Upon some searching, I found the correct magic incantation was openssl s_client -xmpphost -starttls xmpp -connect This was necessary due to the fact that is a different machine than the XMPP server.
  • Finally, I created a user account. Again, on command line. The Debian install has very sane and safe defaults. It disables registrations via XMPP clients by default. Exactly what I want :). Also, MUC (“Group Chats”) creation is limited to server members.
  • Opened up Gajim, added the account. It worked. Yay!
  • Next up, I still have a stale account on, so to check whether server-to-server connections work, I added my old account as a contact. And this worked as well.

(1) The final config section is

  - /var/lib/ejabberd/certs/fullchain.pem
  - /var/lib/ejabberd/certs/key.pem

Current state of my server

  • The warning Invalid certificate in /var/lib/ejabberd/certs/fullchain.pem: at line 57: certificate is signed by unknown CA still appears on server start. Shoot. But I don’t know what to do about it.
  • vCards with Gajim don’t seem to be working. I have no idea why.
  • I don’t particularly care for file exchange / upload. For that, I would need to add another subdomain and twiddle with the config, I guess.

Final remark

For a German guide on how to setup ejabberd, you may want to look at the Kuketz Blog. I only found this blog post after I was mostly finished with my setup.

Thanks also for all the people who helped me during setup on Mastodon <3. I don’t know if they want to be named / listed here, so I rather won’t.