Prosody IM XMPP: A Simple Guide to Core Setup and Optimization

Learn Prosody IM XMPP setup step by step, from install and TLS to modules and speed tuning. Build a fast, private chat server today.

Prosody IM XMPP: A Simple Guide to Core Setup and Optimization

Overview

If you want a chat server that you fully own, Prosody IM XMPP is one of the easiest ways to get there. Prosody is a small, fast XMPP server written in Lua. It runs well on a cheap VPS, it is easy to read and edit, and it works with almost every modern chat app that speaks XMPP. I have set up Prosody for small teams, family groups, and community projects, and the pattern is always the same: a basic install takes less than an hour, and a few smart tweaks make it feel like a proper, polished service.

This guide walks you through the whole path. We will install Prosody, set up your domain and DNS, add encryption, turn on the modules that matter, and then tune the server so it stays quick and stable. No fancy words, just clear steps you can follow.

What Is Prosody and Why Do People Choose It?

XMPP is an open chat protocol. It has been around for more than twenty years, and it is not owned by any one company. Anyone can run a server, and servers can talk to each other, much like email.

Prosody is one of the most popular XMPP servers. Here is why people pick it:

  • It is light. A small server with a few dozen users can run on 512 MB of RAM, and often less.
  • The config is one readable file. You edit a Lua file, and you can understand what every line does.
  • It has a strong module system. You turn features on by adding a name to a list.
  • It is active. The project ships regular releases and keeps up with new XMPP standards.

Compared with bigger servers like ejabberd or Openfire, Prosody trades some heavy clustering features for simplicity. For most small and medium setups, that is a good trade. If you need to serve millions of users at once, look at ejabberd. If you want a tidy, self-hosted XMPP server for a team, a community, or yourself, Prosody is a great fit.

What You Need Before You Start

Get these things ready first. It saves a lot of back and forth later.

  • A Linux server (Debian or Ubuntu is the easiest path)
  • A domain name you control, such as example.com
  • Root or sudo access
  • Ports 5222 (client connections), 5269 (server-to-server), and 80/443 or 5281 (web features) open on your firewall
  • A basic comfort with the command line

A quick tip: decide on your domain name early. Your chat addresses will look like alice@example.com, and changing the domain later is painful.

Installing Prosody IM XMPP on Debian or Ubuntu

The version in the default Ubuntu or Debian repository is often a little old. The Prosody team runs its own package repository, and using it gets you newer releases and security fixes faster. Check the official Prosody download page for the current repository instructions, because the key and URL can change.

Once the repository is added, the install is short:

sudo apt update
sudo apt install prosody

After that, confirm it is running:

sudo systemctl status prosody

Prosody stores its main config at /etc/prosody/prosody.cfg.lua. Take a backup before you touch it:

sudo cp /etc/prosody/prosody.cfg.lua /etc/prosody/prosody.cfg.lua.bak

Getting Your DNS Right

This is where many first-time setups go wrong. XMPP clients and other servers use DNS to find yours, so it needs to be set up correctly.

At a minimum you need an A record (and AAAA if you use IPv6) pointing your domain, or a hostname like xmpp.example.com, to your server. If your chat domain is example.com but the server lives at xmpp.example.com, add SRV records so others know where to connect:

_xmpp-client._tcp.example.com. 86400 IN SRV 5 0 5222 xmpp.example.com.
_xmpp-server._tcp.example.com. 86400 IN SRV 5 0 5269 xmpp.example.com.

You will also want records for the extra services you plan to run, such as conference.example.com for group chat and upload.example.com for file sharing. Point them to the same server.

Wait a little for DNS to update before you test. Patience here saves you from chasing errors that are not real.

Prosody Configuration File: The Core Setup

Now for the heart of it. Open /etc/prosody/prosody.cfg.lua. It looks long at first, but you only need to care about a few parts.

Admins

admins = { "you@example.com" }

This gives your account admin rights. You do not need to create the account yet, but the address must match the one you will register.

Modules

The modules_enabled list is where you switch features on. A solid starting list looks like this:

modules_enabled = {
    -- Core
    "roster"; "saslauth"; "tls"; "dialback"; "disco";
    "carbons"; "pep"; "private"; "blocklist"; "vcard4"; "vcard_legacy";
    "limits"; "version"; "uptime"; "time"; "ping"; "register";
    "admin_adhoc";

    -- Modern chat features
    "mam"; "smacks"; "csi_simple"; "cloud_notify";
    "bookmarks"; "server_contact_info";
}

Some names may already be there in the default file. The point is to know what each one does, so let us go through the important ones in a moment.

Security Basics

c2s_require_encryption = true
s2s_require_encryption = true
s2s_secure_auth = false
allow_registration = false

Setting c2s_require_encryption to true means users cannot connect without TLS. Turning allow_registration off stops strangers from creating accounts on your server, which is what you want for a private setup. If you run a public server, you can turn it on, but pair it with rate limits and abuse controls.

About s2s_secure_auth: setting it to true forces strict certificate checks for server-to-server links. That is safer, but it can block chats with servers that have bad certificates. Start with false, and raise it once you are comfortable.

Authentication and Storage
lua
authentication = "internal_hashed"
storage = "internal"

The internal_hashed option stores password hashes instead of plain text, which is the right default. The internal storage keeps data in simple files. This is fine for small servers. For bigger ones, you can switch to SQL storage, which we will cover in the optimization part.

Your Virtual Host

At the bottom of the file, define your domain:

VirtualHost "example.com"

A virtual host is just the chat domain your users belong to. You can add more than one if you want to host several domains.

Group Chat and File Sharing Components

Component "conference.example.com" "muc"
    modules_enabled = { "muc_mam" }

Component "upload.example.com" "http_file_share"

The first creates a multi-user chat service (MUC). The muc_mam module stores room history so people who join late can catch up. The second enables file uploads, so photos and documents work smoothly in mobile apps.

Setting Up a Prosody TLS Certificate

Encryption is not optional today. Clients will complain or refuse to connect without a valid certificate.

The easiest route is Let’s Encrypt with Certbot. Get a certificate that covers your main domain and the extra subdomains:

sudo certbot certonly --standalone \
  -d example.com -d conference.example.com -d upload.example.com

Then import it into Prosody:

sudo prosodyctl --root cert import /etc/letsencrypt/live

This copies the certificates to a place Prosody can read them. To keep them fresh, add a renewal hook so Prosody picks up new certificates automatically:

sudo tee /etc/letsencrypt/renewal-hooks/deploy/prosody.sh <<'EOF'
#!/bin/sh
prosodyctl --root cert import /etc/letsencrypt/live
systemctl reload prosody
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/prosody.sh

Restart Prosody and you should be in good shape.

Creating Your First Users

With everything set, create an account:

sudo prosodyctl adduser you@example.com

Prosody will ask you for a password. Now try logging in with a client such as Conversations or Monal on your phone, or Gajim and Dino on the desktop. If it connects and you can message another test account, your core setup works.

Run the Built-In Check Tool

Before you celebrate, run this:

sudo prosodyctl check

It looks at your config, DNS, and certificates and tells you what is wrong in plain language. I run it after every change. It catches things like missing SRV records, certificates that do not cover a subdomain, or modules that are enabled in the wrong place. Read the warnings slowly, because they usually tell you exactly what to fix.

The Prosody Modules That Matter Most

A good chat experience on a phone depends on a handful of modules. Here is what they do in simple terms.

mod_mam (Message Archive Management). This stores your message history on the server. When you log in on a new device, your chats show up. Without it, each device only sees new messages.

mod_smacks (Stream Management). Phones drop connections all the time. Smacks lets a client reconnect and resume where it left off without losing messages.

mod_csi_simple (Client State Indication). When your phone screen is off, this module holds back low-priority updates like typing notices and presence changes. It saves battery and data.

mod_cloud_notify. This sends push notifications, so your phone gets alerts even when the app is asleep. On iPhones especially, this is what makes a self-hosted server feel usable.

mod_carbons. If you use several devices, carbons copy messages to all of them, so a chat stays in sync everywhere.

mod_http_file_share. Handles file uploads with limits you can control.

mod_limits. Sets rate limits so one noisy or broken client cannot hurt the whole server.

There is also a bigger library of community modules. In recent versions you can install them with prosodyctl install, which is much cleaner than copying files by hand. Only add what you need. Every extra module is one more thing to update and check.

Prosody Optimization: Keeping It Fast and Steady

A default Prosody install already runs well. Still, a few changes will make it faster, safer, and easier to maintain as you grow.

1. Use the Right Network Backend

Recent Prosody versions use an efficient event loop by default (epoll on Linux). If you are on an older release, you can set the backend yourself:

network_backend = "epoll"

If that option is not available in your version, the libevent backend is the next best choice. Either one handles many connections far better than the old select-based loop.

2. Move to SQL Storage When You Grow

Plain file storage is simple, but message archives grow large. Once you have many users or a busy archive, use a database:

storage = "sql"
sql = {
    driver = "PostgreSQL";
    database = "prosody";
    username = "prosody";
    password = "your-password";
    host = "localhost";
}

PostgreSQL and MySQL are both supported, and SQLite works well for small servers. A common trick is to keep most data in files but send only the archive to SQL:

storage = {
    archive = "sql";
}

That gives you fast searching where it counts without changing everything.

3. Control Your Archive Size

Old messages take space. Tell Prosody how long to keep them:

archive_expires_after = "1y"

You can use shorter values like "3m" for three months. Pick a window that fits your users. Some teams want a full year, others only a few weeks. Being clear about this also helps with privacy, since you are not keeping data forever by accident.

4. Set Sensible Limits

limits = {
    c2s = { rate = "10kb/s"; };
    s2sin = { rate = "30kb/s"; };
}

These values are a starting point. Raise them if users send lots of media directly through the stream, and lower them on very small servers. The goal is to stop abuse without slowing normal chat.

5. Set File Upload Limits

http_file_share_size_limit = 10 * 1024 * 1024
http_file_share_expires_after = 60 * 60 * 24 * 7

This caps uploads at 10 MB and deletes files after a week. Without limits, a disk can fill up quickly, and a full disk is the most common cause of a sudden outage on a small server.

6. Tune Logging

Logs help you fix problems, but too much logging wastes disk and time. A calm setup looks like this:

log = {
    info = "/var/log/prosody/prosody.log";
    error = "/var/log/prosody/prosody.err";
}

Switch to debug only when you are chasing a specific issue, and switch back after. Also make sure log rotation is on so old logs do not pile up.

7. Keep Lua and Prosody Updated

Newer Lua versions and newer Prosody releases include speed and security fixes. Update on a schedule, for example once a month, and read the release notes first. Test big upgrades on a spare server if you can.

8. Watch Resource Use

Prosody has a built-in way to check its stats using prosodyctl shell. You can see how many users are connected, how much memory it uses, and what modules are loaded:

sudo prosodyctl shell
> c2s:show()
> module:list("example.com")

If memory grows over time without dropping, look at recently added community modules first. They are the usual suspect.

Security Habits That Pay Off

A fast server that is not safe is not worth much. A few habits go a long way:

Keep allow_registration off unless you truly need public sign-ups. Use a firewall and only open the ports you need. Use strong, unique passwords, or better, ask users to use a password manager. Back up /etc/prosody and your data folder or database on a schedule, and test that you can restore. Turn on mod_tombstones and other protections if you run a public server, to reduce account takeover risk. Run prosodyctl check after every change.

You can also test your server against public XMPP compliance tools. They give you a score and point out missing features, which is a quick way to see if your setup matches what modern apps expect.

Common Problems and Simple Fixes

Clients cannot connect. Check DNS first, then your firewall, then your certificate. Most connection problems come from one of those three.

Certificate errors. Make sure the certificate covers every domain and subdomain you use, and that you imported the latest one into Prosody.

Messages do not reach other servers. Port 5269 is probably blocked, or your SRV records are wrong.

No push notifications on iPhone. Confirm cloud_notify is enabled and that your client app supports it. Some apps need extra setup.

File uploads fail. Check that the upload subdomain has DNS and a valid certificate, and that the size limit is not too low.

Conclusion

Setting up Prosody IM XMPP does not have to be hard. The whole flow is simple: install the server, point your DNS the right way, get a proper TLS certificate, enable a few key modules, and create your users. From there, optimization is about small, steady choices. Use SQL when the archive grows, set clear limits, keep logs tidy, and update on a schedule.

The best part is that you end up with a chat system that belongs to you. No ads, no lock-in, and no surprise changes from a big company.

Ready to try it? Spin up a small VPS this weekend, follow the steps above, and run prosodyctl check when you are done. Start with a couple of test users, get comfortable with the config file, and grow from there. Your own private chat server is closer than you think.

Frequently Asked Questions

Prosody is a lightweight server that runs the XMPP chat protocol. People use it to host private messaging for teams, families, communities, or businesses, with support for group chats, file sharing, and multi-device sync.

Yes. Prosody is open-source software released under the MIT license. You only pay for the server and domain you run it on.

A small server with a few dozen users can run on around 256 to 512 MB of RAM. Larger groups and busy archives will need more, but Prosody stays light compared with many other chat servers.

Yes. Android users often pick Conversations, and iPhone users can use apps like Monal or Siskin IM. For good mobile behavior, enable mod_smacks, mod_csi_simple, and mod_cloud_notify.

Small servers do fine with the default file storage. If you have many users or a large message archive, SQL (PostgreSQL, MySQL, or SQLite) gives better speed and easier management.

Force TLS for client and server connections, turn off open registration, keep the software updated, use a firewall, back up your data, and run prosodyctl check after changes.

Prosody is lighter and easier to configure, so it suits small and mid-sized setups. Ejabberd is built for very large deployments and clustering, but it takes more effort to set up and manage.

Add a MUC component in your config, such as Component "conference.example.com" "muc", then create a DNS record and certificate for that subdomain. You can add muc_mam to store room history.

Yes. Add another VirtualHost entry for each domain, set up DNS and certificates for it, and Prosody will serve them all.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Get in Touch

Get Started with Us Today!

Looking to set up or optimize your Jitsi? Let's connect and make it happen.