Prosody

Prosody is a modular XMPP (aka. “Jabber”) server written in the Lua programming language. It is one of the most popular servers implementing the XMPP core protocol defined in RFC 6120 and bundles an extensive number of modules that implement various XMPP features (called XMPP Extension Protocols, or XEPs). Modules conform to a simple interface, making them easy for developers to write in order to add additional features to a given Prosody server. Prosody can support OMEMO-capable clients in its default configuration.

To be useful, Prosody must be paired with an XMPP client. See the Tech Autonomy guide to using digital text chat and talk tools for details on client installation and configuration.

Installing

Most operating system distributions provide the prosody package. Install it on a Debian-based GNU/Linux system with:

sudo apt update && sudo apt install prosody

See the Prosody downloads page for complete installation instructions.

Configuring

There are numerous different configurations in which Prosody can be set up. This page describes the configurations useful for and familiar to the Tech Autonomy Infrastructure committee needs.

Isolated service running a minimal Prosody server with application-level user access control

This section describes configuring Prosody to invoke a long-running single prosody server process. It serves users at a single domain and intentionally does not federate with other XMPP servers. It offers one-to-one and group chat private text messaging by supporting OMEMO clients. (See the Hardening section for information on how to require, rather than merely support, OMEMO-encrypted messages).

  1. Set up the prosody user if installing Prosody did not already add such a user (use getent passwd prosody to see if such a user has already been created):
    sudo adduser --system --home /YOUR/CHOSEN/PROSODY/HOME/FOLDER prosody
    
  2. Configure the Prosody daemon process itself. This is done by writing a configuration file and placing it in a conventional place, which is usually /etc/prosody/prosody.cfg.lua for most GNU/Linux server systems. Paste the following configuration file, being careful to change the values of /YOUR/CHOSEN/PROSODY/HOME/FOLDER and YOUR_VIRTUALHOST_DOMAIN to sensible ones as you desire:
    -- FILE: /etc/prosody/prosody.cfg.lua
    --
    -- Main Prosody XMPP server configuration file.
    --
    -- This file describes the desired behavior the Prosody XMPP server.
    -- See https://prosody.im/doc/configure for more details.
    
    -- Filesystem location of the Prosody server's persistent data.
    -- This is usually the home directory of the Prosody server's OS user account.
    -- Defaults to "/var/lib/prosody" on most GNU/Linux systems.
    data_path = "/YOUR/CHOSEN/PROSODY/HOME/FOLDER"
    
    -- Set the default interfaces on which Prosody will listen for connections.
    -- For more information, see https://prosody.im/doc/ports
    --interfaces = { "127.0.0.1" } -- Listen only for local connections (for example, for a Tor-only XMPP service).
    
    -- List of accounts that have administrative access over XMPP from their XMPP
    -- clients. Keep this list empty to disallow remote administration over XMPP.
    admins = {
    }
    
    -- List of modules loaded into the server during runtime.
    modules_enabled = {
        -- Generally required
        "saslauth"; -- Required to allow XMPP clients to authenticate with the server (i.e., to log in).
        "tls";      -- RFC 7590. Required for TLS-protected c2s and s2s connections.
        "disco";    -- Service Discovery XEP-0030: Usually required for OMEMO encryption as implemented in most clients.
        "register"; -- In-Band Registration XEP-0077: Required to allow users to change their own passwords.
        "pep";      -- Personal Eventing Protocol XEP-0163: Required for OMEMO encryption, user avatars, etc.
        "roster";   -- Roster Versioning XEP-0237: Required for basic Instant Message (IM) functionality as well as OMEMO.
    
        -- Nice to have
        "carbons";  -- Message Carbons XEP-0280: Keeps multiple clients in sync.
    }
    
    -- List of automatically loaded modules that you want to disable.
    -- Leave this list empty to load all Prosody core features.
    modules_disabled = {
        "s2s"; -- Disallow server-to-server connections (XMPP federation).
    }
    
    -- Location of the Prosody server's PID file.
    -- This is required for the `prosodyctl` administrative command to function.
    pidfile = "/var/run/prosody/prosody.pid"
    
    -- Authentication mechanism to use (with `saslauth`).
    -- This defaults to `internal_plain`, which does not hash user passwords.
    authentication = "internal_hashed" -- Hash user passwords in the storage backend.
    
    -- Disable account creation by default, for security
    -- For more information see https://prosody.im/doc/creating_accounts
    allow_registration = false
    
    -- Uncomment this to require that client-to-server (c2s) connections be encrypted with TLS.
    --c2s_require_encryption = true
    
    -- Logging configuration
    -- For advanced logging see https://prosody.im/doc/logging
    log = "/dev/null" -- Blackhole all logs. Logs contain metadata such as user login/logout times.
    
    VirtualHost "YOUR_VIRTUALHOST_DOMAIN"
    Component "conference.YOUR_VIRTUALHOST_DOMAIN" "muc"
        restrict_room_creation = "local"
    
  3. As the above configuration does not permit users to register new accounts (i.e., allow_registration = false), user accounts must be created by a server administrator manually. To create a user account named alice who can log in to the Prosody server, assuming YOUR_VIRTUALHOST_DOMAIN is example.local, invoke prosodyctl(1) as follows:
    sudo prosodyctl adduser alice@example.local
    

    You will then be prompted to enter a password for the new user account. Repeat this step for all users you wish to create. The user can then log in with an XMPP client using the initial password provided to the prosodyctl adduser command. Once authenticated, the user can then use an XMPP client tha supports XEP-0077’s password change feature to change their password to one known only to them.
  4. Restart the Prosody server:
    sudo prosodyctl restart
    

To test that this is working, check to see if Prosody is now bound to a listening network socket and accepting incoming requests:

sudo ss --listening --tcp --numeric --processes | grep lua # grep for `lua` as Prosody runs via the Lua interpreter.
LISTEN     0      128          *:5222                     *:*                   users:(("lua5.2",pid=5199,fd=5))
LISTEN     0      128         :::5222                    :::*                   users:(("lua5.2",pid=5199,fd=6))

Administering

TK-TODO: Some basic information on adminstering the server: what data is where?

Hardening

TK-TODO: Some things that should be done include…

  • Disable logging.
  • Enforce message encryption policies: modules.prosody.im/mod_e2e_policy.html
  • Consider alternate storage backends (SQL databases, for instance).
  • Create an AppArmor profile.
  • Run Prosody within a (Docker?) container.

Recovering

TK-TODO: Backups should be considered.

Provisioning

The AnarchoTech NYC collective provides an Ansible role for provisioning a Prosody server that runs on a Raspberry Pi. It can be installed in your local $ANSIBLE_ROLES_PATH (see Ansible Configuration Settings) for use with an Ansible project with:

ansible-galaxy install https://github.com/AnarchoTechNYC/ansible-role-prosody/archive/master.tar.gz

Notes

DNS resolution

Prosody does not use the /etc/hosts file, nsswitch, or anything similar. Instead, Prosody provides a stub DNS resolver for A queries. This is because the standard practice for XMPP is to use SRV records. If there is no relevant SRV records for the query, it’ll just use the A/AAAA records.

In order to resolve a domain name that is not available via DNS, you must either run your own DNS server, or you may be able to use the s2soutinjection module.

Using Tor

TK-TODO: Discuss mod_onions. See also the blog of Thijs Alkemade.

This plugin allows Prosody to connect to other servers that are running as a Tor hidden service. Running Prosody on a hidden service works without this module, this module is only necessary to allow Prosody to federate to hidden XMPP servers.

More or less, this has to be included in the config file as such:

VirtualHost "555abcdefhijklmn.onion"
    modules_enabled = { "onions" };

See also