Configuring XMPP services (revision 2)

Introduction

This procedure describes how Alexis Huxley set up a XMPP server.

Prologue

  1. Note that, because this procedure starts with setting up a proper certificate and that requires authentication, DNS may need to be modified before the XMPP server itself is installed. This means there is noticable service downtime.
  2. Set some environment variables used in the rest of this procedure:
    FQDN=<fqdn-of-server-as-seen-from-internet>    #  e.g. FQDN=jabber.pasta.freemyip.com

Let’s Encrypt certificate

  1. Ensure that the front-end webserver to does not forward requests that it receives over https to the mail server (it is not needed).
  2. Ensure that the front-end webserver forwards requests that it receives over http to the mail server, with a configuration something like this:
    <VirtualHost *:80>
        ServerName jabber.pasta.freemyip.com
        ServerAdmin webmaster@dont-use-this-address
        CustomLog /var/log/apache2/jabber.pasta.freemyip.com/jabber.pasta.freemyip.com-access.log combined2
        ErrorLog /var/log/apache2/jabber.pasta.freemyip.com/jabber.pasta.freemyip.com-error.log
        LogLevel warn
        ServerSignature Off
    
        <Location />
            ProxyPass http://jabber.pasta.net/
            ProxyPassReverse http://jabber.pasta.net/
        </Location>
    </VirtualHost>
  3. On the DNS server, update the CNAME record for ‘jabber.pasta.freemyip.com’ to point to the new XMPP server.
  4. On the firewall/router make an adjustments to where incoming traffic on ports 5222 and 5269 is sent.
  5. On the XMPP server install and run certbot as follows:
    apt -y install certbot
    certbot certonly --standalone -d  $FQDN

    (The option --standalone will – whenever requesting/renewing a certificate – start a standalone internal webserver to allow letsencrypt.org authenticate the renewal request; /etc/cron.d/certbot will respect this option when it is used to initially request the certificate.)

  6. Locate the certificate and key generated by certbot:
    find /etc/letsencrypt/live/ -name fullchain.pem -o -name privkey.pem

Prosody

  1. Run:
    apt -y install prosody
    systemctl stop prosody
  2. Edit /etc/prosody/prosody.cfg.lua and make the following global config changes:
    ---------- Server-wide settings ----------
    ...
    interfaces = { "*" }               -- don't listen on IPv6
    ...
    
  3. Create a minimal new virtual host by editing /etc/prosody/conf.avail/$FQDN.cfg.lua to contain only:
    VirtualHost "FQDN"
    ssl = {
        key = "/etc/letsencrypt/live/FQDN/privkey.pem";
        certificate = "/etc/letsencrypt/live/FQDN/fullchain.pem";
    }
    allow_registration = true;
    

    and then replacing all the placeholders by running:

    sed -i "s/FQDN/$FQDN/g" /etc/prosody/conf.avail/$FQDN.cfg.lua
  4. Symlink the new config into place and remove the old config:
    ln -sr /etc/prosody/conf.avail/$FQDN.cfg.lua /etc/prosody/conf.d
    rm /etc/prosody/conf.d/localhost.cfg.lua
  5. Create a script to instruct prosody to reload its configuration when the Let’s Encrypt certificate gets renewed:
    {
        echo '#!/bin/sh'
        echo 'cp /etc/letsencrypt/live/FQDN/fullchain.pem /etc/prosody/certs/FQDN.fullchain.pem'
        echo 'cp /etc/letsencrypt/live/FQDN/privkey.pem /etc/prosody/certs/FQDN.privkey.pem'
        echo 'chown prosody:prosody /etc/prosody/certs/FQDN.fullchain.pem'
        echo 'chown prosody:prosody /etc/prosody/certs/FQDN.privkey.pem'
        echo 'systemctl reload prosody'
    } > /etc/letsencrypt/renewal-hooks/deploy/prosody
    sed -i "s/FQDN/$FQDN/g" /etc/letsencrypt/renewal-hooks/deploy/prosody
    chmod 755 /etc/letsencrypt/renewal-hooks/deploy/prosody

    (I tried to configure prosody to use the Let’s Encrypt certificate in situ and for the hook to just run prosodyctl reload, but prosody does not run as root and therefore lacks access rights, so the above hook is better. In an older version of the this procedure, I used prosodyctl --root cert import, but the method above has the advantage of transparency.)

  6. If migrating to a new server then copy over account information, which is stored in /var/lib/prosody/{accounts,roster,vcard}, remembering to set the owner & group correctly.
  7. Restart the service by running:
    service prosody restart
  8. As an experiment, to improve file transfer time, I edited /etc/prosody/prosody.cfg.lua and commented out the following lines:
    modules_enabled = {
        ...
        -- "limits";
        ...
    }
    
    -- limits = {
    --    ...
    -- }
  9. To test:
    1. In pidgin go to Tools–>Certificates and select the appropriate certificate and click ‘Get Info’.
    2. Verify the ‘Activation date’ matches the time at which the above certbot command was run.

    See also

    1. Computing
    2. Download Prosody