Originally published on 14 August 2021
Last updated on 29 September 2021
Contents
UPDATE from 29 September 2021:
Please be sure to check out my updated implementation process and server configuration in this post. It’s probably still worthwhile to first read through the information below to get the relevant context and background if you’re new to Prosody.
A few weeks ago, I published a post on how to create an XMPP server with Prosody. I had to quickly update it with some errata based on feedback I received from one of the developers of Prosody. In this post, I’m going to try to explain a new process to get Prosody up and running based on the project’s actual documentation rather than relying so heavily on third-party tutorials. As before, these steps assume you are installing Prosody on Ubuntu 20.04. This time around, we are also going to try to comply with XEP-0368 by creating additional DNS records to enable client-to-server (c2s) connections over TLS as well as XEP-0045 by enabling multi-user chat (MUC).
The first thing I did was to create a series of A
and SRV
DNS records in my Azure DNS zone based on the Prosody documentation. The A
records were:
Name Type TTL (seconds) Value
@ A 3600 VPS IP Address
rooms A 3600 VPS IP Address
The first A
record points any *.example.com
requests to my server. The second A
record creates the rooms.example.com
subdomain which we’ll use later to set up our multi-user chatrooms.
Next, I created three SRV
records to allow for c2s (plain text), c2s (encrypted over TLS) and server-to-server (s2s) connections:
Name Type TTL (seconds) Priority Weight Port Target
_xmpp-client._tcp SRV 18000 0 5 5222 example.com
_xmpps-client._tcp SRV 18000 0 5 5223 example.com
_xmpp-server._tcp SRV 18000 0 5 5269 example.com
XMPP in general, and Prosody in particular, rely on several ports to accomodate a number of services. The Prosody documentation does a good job of walking you through all of this. For my installation, here are the ports I had to open in my VPS firewall:
Priority Name Port Protocol
300 SSH 22 TCP
350 HTTP 80 TCP
400 HTTPS 443 TCP
450 Client-to-Server 5222 TCP
500 Client-to-Server (TLS) 5223 TCP
550 Server-to-Server 5269 TCP
600 Prosody HTTP Server 5280 TCP
650 Prosody HTTPS Server 5281 TCP
The Source
and Destination
for all inbound port rules were set to Any
. The Action
was set to Allow
.
At this point, you can refer back to my original post on how to install and configure Nginx as well as how to install Prosody. Those steps still apply. Once you’re ready to configure Prosody, we can resume here. We will take care of the TLS encryption for Prosody in subsequent steps.
I first made a backup of the original configuration file for reference and then opened up the file to make changes:
$ sudo cp /etc/prosody/prosody.cfg.lua /etc/prosody/prosody.cfg.lua.original $ sudo vim /etc/prosody/prosody.cfg.lua
Within the file, I updated the admins
line to create a server administrator:
admins = { "admin@example.com" }
In the modules_enabled
section, I uncommented the following modules to enable them:
mam
: Stores chat messages on the server so users can retrieve them.csi_simple
: Enables optimizations for mobile clients.bosh
: Enables BOSH clientswebsocket
: allows XMPP over WebSocketshttp_files
: Enables file sharing.announce
: Enables admins to send announcements to all users.motd:
message of the dayThere are more modules that you can configure but for now, these are the only ones I have selected.
If you do NOT want to allow users to register accounts on your server, be sure to comment out the register
module and set the allow_registration
option to false
.
To select SQLite as the message database, enable the following two lines by removing the leading --
as shown in the following lines:
...
storage = "sql" -- Default is "internal"
...
sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
...
You can decide how long the server will store old chat messages by editing the following line:
...
archive_expires_after = "1w" -- Remove archived messages after 1 week
...
The default period is 1w (one week). Use d for days, w for weeks, and y for years.
To allow XMPP over TLS (to support XEP-0368), I had to add the following lines right after the commented out https_certificate
line but before the Virtual Hosts
section:
-- Location of directory to find certificates in (relative to main config file): certificates = "certs" -- HTTPS currently only supports a single certificate, specify it here: --https_certificate = "/etc/prosody/certs/localhost.crt" -- legacy_ssl_ports = { 5223 } legacy_ssl_ssl = { certificate = "/etc/prosody/certs/example.com.crt"; key = "/etc/prosody/certs/example.com.key"; } ----------- Virtual hosts -----------
In the default configuration, Prosody listens on localhost
or 127.0.0.1
for chat connections. Update this line to replace localhost
with your fully-qualified domain name:
...
VirtualHost "example.com"
...
Finally, it’s time to enable MUC for our server. To do this, we have to add a component which supports multi-user chat. Fortunately, Prosody has one. To configure it, add the following lines at the bottom of the configuration file under the Components
section:
Component "rooms.example.com" "muc"
name = "example.com chatroom"
restrict_room_creation = true
muc_tombstones = true
modules_enabled = {
"muc_mam",
"vcard_muc",
}
Note: Setting restrict_room_creation = true
means that only administrative accounts you defined earlier can create rooms on your server. This also means that you won’t be able to pass the tests for XEP-0313 or XEP-0153 even though you’ve enabled the muc_mam
and vcard_muc
modules. For a bit of a compromise, try setting restrict_room_creation
to "local"
(with the quotes).
Prosody uses TLS certificates to encrypt the connections between the server and the clients. These certificates are the same ones that you use any time you visit a website with an HTTPS URL. We already obtained our Let’s Encrypt TLS certificates from a prior step; we now just need to import it so that Prosody can use it. For more details on this, please consult the Prosody documentation on managing TLS certificates and using Let’s Encrypt.
Before we import the certificates, it’s important that we also obtain certificates for our MUC, which we wouldn’t have done if we followed the previous post’s steps verbatim. Therefore, before we have Prosody import any certs, let’s run the following command:
$ sudo certbot --nginx -d rooms.example.com
Now, all we need to do to make this happen is the following command:
$ sudo prosodyctl --root cert import /etc/letsencrypt/live Imported certificate and key for hosts example.com, rooms.example.com
As you can see, this is much simpler than the process I described in my original post. Thanks Matthew for pointing me in the right direction!
Restart the service for the configuration changes to take effect:
$ sudo systemctl restart prosody.service
Now, we can create our first XMPP user:
$ sudo prosodyctl register username example.com Enter new password: Retype new password:
That pretty much wraps up our installation! Now all we have to do is connect to the server using our client of choice.
Here is an update on how far I’ve come on my prior “to-do” list and what else I’ve added:
Look into using SRV
records instead of just A
record. As described above, I think I’ve got this done now. I’ve been able to keep the DNS configuration relatively simple because both my web server and XMPP server are running on the same machine. For further details, I’d recommend reading this article. For now, though, I think I’m going to keep things as I’ve described them here. If you need help troubleshooting your SRV
DNS record configuration, I’ve since learned of a command-line tool called wrapsrv
that once installed, can be invoked via the command: wrapsrv _xmpps-client._tcp.example.com openssl s_client -connect %h:%p
.
Improve my servers’s compliance score. There are a few sites out there that check your server’s compliance to the various XMPP protocols and specifications. Two of the more popular ones are compliance.conversations.im and xmpp.net though I’ve learned that the latter may not be up to date. Using the former, I’ve gotten my server score up to 57% so there is still a ton of room for improvement.
Active some multi-user chat (MUC) rooms. I think I’m in a good spot here as I was able to configure the basic MUC functionality but there are additional features I’d like to implement such as message archiving, rate limiting, vcard functionality and more.
Figure out Omemo encryption. Or rather, encryption in general as it turns out that Prosody supports Omemo encryption out of the box (as evidenced by the results on compliance.conversations.im). So far, everything I have configured only allows me to chat in plain text. I’ve tried experimenting with turning on encryption with various clients using verbose keys but I’ve not yet been successful. I guess this is why IRC has been able to remain such a simple protocol as it doesn’t even bother dealing with encryption (and why the Matrix client Element is such a pain to use, because it does try dealing with end-to-end encryption, backing up keys, etc.)
Implementing some community modules. There are a few community modules which look interesting to enable. I think the first step is going to be installing them first and then working on enabling them.
I am still working on my own individual setup and testing it out but am much closer than where I was before. Once it’s ready for “production”, I’ll share my XMPP address! In the meantime, I would love to hear how all of you are using XMPP!