How to Set Up Prosody for You and Your Friends

From Nick Faro's Homepage
Jump to navigation Jump to search

Signal seems to have gone closed-source. I like Signal a lot but there are some legitimate criticisms of it-- I never really minded that it's centralized and not federated, but I really don't want to be using a platform that is (currently) lying to its users and claiming to be free and open-source when it's not. I'm no free software maniac, but it just doesn't feel right. Even though it's end-to-end encrypted, so theoretically a compromised server wouldn't reveal my conversations, I started looking for a different solution.

I've heard a lot about federated, self-hostable protocols like XMPP and Matrix, so I decided to explore if it's feasible to switch my small non-programmer friend group over to a self-hosted XMPP server running on a Raspberry Pi in my house.

The two most popular XMPP servers out there are ejabberd and Prosody. I went with Prosody since I found that it's easier to configure (all the settings are basically perfect out of box) and it's less resource hungry, especially nice for running on a Pi. For the following instructions, I'm going to assume you're using a Debian-based OS since that's what I used.

Step 1: Get a Domain Name

Yeah, if you're self-hosting then you pretty much need to set up a domain name for your server. Sucks, but them's the breaks. I bought a .xyz domain for $1 and pointed it at a No-IP domain, then set up my router to do DDNS with No-IP.

Step 2: Install Prosody

Add Prosody's repository in order to get the latest version.

echo deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list

Then install Prosody.

sudo apt-get install prosody

Step 3: Add a VirtualHost for your domain

Open up /etc/prosody/prosody.cfg.lua and scroll down to the very bottom. Add a line like this:

VirtualHost "<your domain>"

Step 4: Enable multi-user-chat and file sharing

Since we want to be able to create group chats, add these lines below your VirtualHost line. "MUC" means Multi-User Chat in XMPP parlance and just means group chats.

Component "conference.<your domain>" "muc"
modules_enabled = {

To enable file uploading (pictures, audio, etc) put these lines right below that:

Component "upload.<your domain>" "http_upload"
http_host = "<your domain>"

We now have a usable XMPP server, but it's not complete yet-- we need to enable some plugins which enable some useful features that most people will want.

Step 5: Get the Prosody community modules

A few plugins we need are part of the Prosody community modules repository.

First, install mercurial.

apt-get install mercurial

Then download the community modules repository somewhere. I put it in my home directory but you can put it anywhere.

hg clone prosody-modules

Step 6: Set up the community modules

Since Prosody scans plugin directories for everything, and some modules are part of both the community repository and the default pack-in Prosody collection, they recommend creating a separate folder called prosody-modules-enabled, adding THAT to Prosody's plugin path, and then symlinking the modules you want into the directory. So let's do that for the modules we want to use.

mkdir prosody-modules-enabled
cd prosody-modules-enabled
ln -s ../prosody-modules/mod_cloud_notify
ln -s ../prosody-modules/mod_http_upload
ln -s ../prosody-modules/mod_muc_cloud_notify
ln -s ../prosody-modules/mod_smacks

mod_cloud_notify and mod_mud_cloud_notify enable mobile clients such as ChatSecure, Monal and to send push notifications to your phone when you receive a message.

mod_http_upload enables you to share pictures and files in your chats.

mod_smacks is an enhancement which allows spotty or terminated sessions to be resumed without discarding messages in the queue. This is useful for mobile devices on mobile data networks.

Step 7: Enable the modules

Go back into /etc/prosody/prosody.cfg.lua and set a few things.

Add your prosody-modules-enabled folder to the list of plugin_paths

plugin_paths = { "/home/pi/prosody-modules-enabled" }

Add these 2 lines inside the modules_enabled table:


Enable other modules as you see fit.

Below the modules-enabled table, put these 2 lines:

push_notification_with_body = false;
push_notification_with_sender = true;

This allows push notifications to be sent-- you don't want to include the body of the message in the notification, because then Google or Apple can read it, defeating the point of encryption! I enabled the sender part though, since the NSA can already detect which IPs are connecting to your server and figure out who all is talking. Besides, your JID (Jabber IDs) can be anonymous usernames.

Step 8: Set up Let's Encrypt

If you want people to be able to connect to your server, chat, and upload files without certificate errors/warnings, then you'll need an SSL certificate. Luckily this is fairly easy to set up.

First, install certbot:

sudo apt-get install certbot

Then, create a new certificate for your server:

sudo certbot certonly --standalone --preferred-challenges http -d <your domain> -d upload.<your domain>

Remember to open up port 80 on your router for this to work. Once you've got your certificates, you need to import them into Prosody.

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

You can add this as a hook to your certbot so that it always gets called when certbot renews its certificate. Open up /etc/letsencrypt/renewal/<your domain>.conf and add this line at the very bottom:

renew_hook = prosodyctl --root cert import /etc/letsencrypt/live

Step 9: Enable the HTTPS certificate

In order to serve files from its internal HTTP server, Prosody also needs a HTTPS certificate. Fortunately, you can use the one you just created.

Open /etc/prosody/prosody.cfg.lua and go to the line which defines https_certificate (it might be commented out) and put this:

https_certificate = "/etc/prosody/certs/<your domain>.crt"

Step 10: You're basically done

Now we have everything we need. The server should be fully configured and ready to go.

Be sure to:

  1. Run sudo systemctl restart prosody for your server to reload the config file and restart itself.
  2. Port forward ports 5222, 5280, and 5281 so that you can connect to your server.
  3. Add a user for yourself! Do sudo adduser <username>@<yourdomain> and put in a password. You can also create accounts for your friends, and they can change their passwords later.

Connect up using a client such as Gajim, and you're off to the races with a private chat server that's 100% your own. Be sure to turn on OMEMO in your chats so that your messages are end-to-end encrypted! Since you run the server, it's actually okay to send "unencrypted" messages since everything is going through TLS in the first place, but it's nice to have that extra layer of protection. Since files in XMPP are shared via an HTTPS server, you definitely want OMEMO to encrypt your files as well, since otherwise you'll be serving your media to the open web!

There's more you can do, such as enabling federation or installing more plugins, but that's out of the scope of this article.

Special thanks go to the folks in the Prosody IM Chatroom ( for helping me get set up. Note that you'll have to enable federation in order to join that link using your current server.