How to setup a prosody server

In this guide i’m going to show how to make a prosody (XMPP) server, this guide will only cover the bare minimum (no extensions) + the http upload mod, so you can send files.


  1. A domain (you can use something like or if you don’t have any. My domain in this thing is I got it in
  2. A server running a good operating system (Debian, FreeBSD…) I’m using a FreeBSD machine in this guide.


  1. prosody
  2. nginx
  3. something that enables the mod_perl in nginx, in FreeBSD, it is in the nginx-full package, or you can choose to install it while building nginx using the ports. In Debian you can install the libnginx-mod-http-perl package
  4. Certificates, we are going to use certbot here.


In FreeBSD, you simply run pkg install prosody prosody-modules nginx-full or you can choose to build it from ports.


Here is where the ""“hard part”"" comes, in Debian and other good operating systems, the configuration files are located in /etc/prosody, in FreeBSD they’re located at /usr/local/etc/prosody. The main configuration file is prosody.cfg.lua but you can add multiple configurations file in the .conf.d folder.

The configuration file has a lot of comments so use them as guide. First of all is to add admins to the server:

admins = {}

The next line is the modules_enabled, if you want to enable some modules, add them here, some modules can be smacks, for example. but, again, this guide only covers the minimum.

Next thing you should check is the allow_registration parameter, should be false unless you’re going to make a public server.

Next, you can configure prosody to use sql as user storage, but in this case we are just going to do the internal thing. Make sure that it is internal_hashed.

Now, skip until the “VirtualHost” Here you will configure the XMPP VirtualHost for the JID.

Note that configuration bellow “VirtualHost” will only affect that VirtualHost, until there’s a next VirtualHost or “Component”. Single domain servers should have only one “VirtualHost”

By default VirtualHost value is “localhost” change it to your domain: VirtualHost ""

Next, you have to add the ssl certificates to it. to use we are going to generate them using certbot

To generate the certificates, run certbot certonly --rsa-key-size=4096 -d your-domain, if you have nginx running, stop it, so you can use the temporary server option, which has never failed me. Your certificate will be in (usr/local)/etc/letsencrypt/youtdomain/fullchain.pem.

prosody includes a command to import certbot certs so you don’t have to bother with permissions, to do this simply run prosodyctl –root cert import /usr/local/etc/letsencrypt/live/

Now, you have to give prosody that certificate, you have to put it twice for some reason, like this:

ssl = { 
    key = "certs/";
    certificate = "certs/";

VirtualHost ""

ssl = { 
    key = "certs/";
    certificate = "certs/";

now, run prosodyctl check, you should get an output like this

Checking config...

Checking DNS for host
    Host does not seem to resolve to this server (IPv6)

Checking certificates...
Checking certificate for
  Certificate: /usr/local/etc/prosody/certs/

All checks passed, congratulations!

Which means everything is working! now you have to create an user to test it, to do this, run something like this prosodyctl adduser, maybe you should create first the admin’s account. So I created the Wintermute account.

It will ask for a password, so enter it. Now it’s time to test it, you can use any client. I recommend poezio/gajim/dino/profanity

Before testing, you have to, obviously, start the server, in freebsd you’d do something like service prosody start, probably the same in Debian.

If you can log in, probably everything works.

Uploading files

Now you have the bare-bones XMPP server, but you probably want it to upload files, you can use one of these:

We are going to use mod_http_upload_external because it’s more stable and have more benefits over the regular one. There are bunch of implementations of mod_http_upload_external but we are going to use the perl one because it’s the one that worked for me.



You have to add this to the bottom of the prosody config file

Component "" "http_upload_external"
http_upload_external_base_url = ""
http_upload_external_secret = "BURDOBORDO:DDDD:DDD:--"

Please note the “/” at the end of the URL

Create a new site under sites-enabled in nginx configuration folder with something like this.

server {
    # Specify directives such as "listen", "server_name", and TLS-related
    # settings for the "server" that handles the uploads.
    # Uploaded files will be stored below the "root" directory. To minimize
    # disk I/O, make sure the specified path is on the same file system as
    # the directory used by Nginx to store temporary files holding request
    # bodies ("client_body_temp_path", often some directory below /var).
    root /usr/local/var/www/upload;

    # Specify this "location" block (if you don't use "/", see below):
    location / {
        perl upload::handle;

    # Upload file size limit (default: 1m), also specified in your XMPP
    # server's upload module configuration (see below):
    client_max_body_size 100m;

now, in your nginx.conf add something like this in the http section

load_module modules/;
http {
perl_modules /usr/local/lib/perl; # Path to

Run these commands

mkdir -p /usr/local/lib/perl
wget -O /usr/local/lib/perl/

Now you have to edit /usr/local/lib/perl/ to change the password for the one you put in prosody configuration.

my $external_secret = 'BURDOBORDO:DDDD:DDD:--';

Make the directory for uploaded files mkdir /usr/local/var/www/upload and use chown to give it ownership to nginx user, in debian is www-data and in freebsd is www, but in others like arch is nginx.

SSL for the upload site

We used https:// in the prosody configuration, you can use http:// if you want, but it’s not recommended. We are going to simply use the --nginx certbot flag for this. So you have to install the certbot nginx plugin. Simply run certbot --nginx --rsa-key-size=4096 -d Process shold be automatic.

Try uploading a file in dino, it shold work.

The next step will be adding other modules to your XMPP server, such as MUC or some others, these are very obvious to install. Only RTFM :). If you are going to make it compatible with more extensions, create a tester account ( and add it to If you click on the squares of why the thing isn’t working, it will give you a guide of how to install that. Most modules are simply adding the modules to the modules_enabled section. You should install smacks and bookmarks!