Samir Parikh / Blog

Originally published on 14 August 2021

Last updated on 29 September 2021


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).

Configure DNS

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 * requests to my server. The second A record creates the 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
_xmpps-client._tcp  SRV     18000           0           5       5223
_xmpp-server._tcp   SRV     18000           0           5       5269

Open Firewall Ports

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.

Configure Nginx and Install Prosody

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.

Update Prosody Configuration File

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 = { "" }

In the modules_enabled section, I uncommented the following modules to enable them:

There 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/";
  key = "/etc/prosody/certs/";

----------- Virtual hosts -----------

In the default configuration, Prosody listens on localhost or for chat connections. Update this line to replace localhost with your fully-qualified domain name:

VirtualHost ""

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 "" "muc"
        name = " chatroom"
        restrict_room_creation = true
        muc_tombstones = true
        modules_enabled = {

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).

Configure TLS Encryption for Prosody

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

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,

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
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.

Next Steps

Here is an update on how far I’ve come on my prior “to-do” list and what else I’ve added:

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!