Home

Awesome

Prosody XMPP Docker image

Docker Git repository size Docker pulls Docker stars Github open issues Github open pull requests

This docker image provides you with a configured Prosody XMPP server. The image is based on debian:bookworm-slim. The server was tested using the Android App Conversations and the Desktop client Gajim. Multiple architectures are supported. I use it on my raspberry pi 4.

While Conversations got everything set-up out-of-the-box, Gajim was used with the following extensions:

Table of Contents

Features

Requirements

Image Details

Ports

The following ports are exposed:

Directories

Data

Path: /usr/local/var/lib/prosody/.

Bundled modules

Path: /usr/local/lib/prosody/modules/.

Additionally installed prosody modules

Path: /usr/local/lib/prosody/custom-modules/.

Config

Path: /usr/local/etc/prosody/.

SSL certificates

Path: /usr/local/etc/prosody/certs/.

Uses automatic location to find your certs.

The http_upload module and the legacy_ssl module do not use the same search algorithm for the certificates. See service certificates.

The settings https_ssl and legacy_ssl_ssl in 05-vhost.cfg.lua configures the certificates to certs/domain.tld/fullchain.pem and certs/domain.tld/privkey.pem for legacy_ssl and to certs/DOMAIN_HTTP_UPLOAD/fullchain.pem and certs/DOMAIN_HTTP_UPLOAD/privkey.pem for http_upload where DOMAIN_HTTP_UPLOAD is an environtment variable.

Folder structure

An example certificate folder structure could look like this:

certs
├── conference.domain.tld
│   ├── fullchain.pem
│   └── privkey.pem
├── proxy.domain.tld
│   ├── fullchain.pem
│   └── privkey.pem
├── upload.domain.tld
│   ├── fullchain.pem
│   └── privkey.pem
└── domain.tld
    ├── fullchain.pem
    └── privkey.pem

Thats how Let's encrypt certbot does it out of the box.

Symlinks

certbot creates the structure and uses symlinks to the actual certificates. If you mount them like that prosody somehow does not find them. I copied them to a folder named certs next to my docker-compose.yml and made sure to use the -L flag of cp. This makes cp follow symbolic links when copying from them. For example cp -L src dest.

Permissions

See official documentation for more information. Check Volumes permissions as well.

Run

I recommend using a docker-compose.yml file:

version: '3.7'

services:
  server:
    image: sarasmiseth/prosody:latest
    restart: unless-stopped
    ports:
      - "5000:5000"
      - "5222:5222"
      - "5223:5223"
      - "5269:5269"
      - "5281:5281"
    environment:
      DOMAIN: domain.tld
    volumes:
      - ./certs:/usr/local/etc/prosody/certs
      - ./data:/usr/local/var/lib/prosody

Boot it via: docker compose up -d.

Inspect logs: docker compose logs -f.

Volumes permissions

The prosody user inside the container has the uid=999 and gid=999. If you use the example docker-compose.yml from above make sure, that the ./data folder and the ./certs folder have the correct permissions.

sudo chown 999:999 ./certs
sudo chown 999:999 ./data

Docker tags

https://hub.docker.com/r/sarasmiseth/prosody/tags

TagDescription
edgeThis tag points to the latest version build from the newest commit in the dev branch.
nightlyThis tag points to the latest version build from the newest commit in the dev branch. It gets rebuild every night.
latestThis tag points to the latest version build from the latest commit that is tagged in git. See releases.
vX.Y.ZThere is a tag for each release.

Configuration

Environment variables

VariableDescriptionTypeDefault value
ALLOW_REGISTRATIONWhether to allow registration of new accounts via Jabber clientsoptionaltrue
DOMAINdomainrequirednull
DOMAIN_HTTP_UPLOADDomain which lets clients upload files over HTTPoptionalupload.DOMAIN
DOMAIN_MUCDomain for Multi-user chat (MUC) for allowing you to create hosted chatrooms/conferences for XMPP usersoptionalconference.DOMAIN
DOMAIN_PROXYDomain for SOCKS5 bytestream proxy for server-proxied file transfersoptionalproxy.DOMAIN
DOMAIN_PUBSUBDomain for a XEP-0060 pubsub serviceoptionalpubsub.DOMAIN
AUTHENTICATIONauthenticationoptional"internal_hashed"
LDAP_BASELDAP base directory which stores user accountsrequired if AUTHENTICATION is "ldap"
LDAP_SERVERSpace-separated list of hostnames or IPs, optionally with port numbers (e.g. “localhost:8389”)optional"localhost"
LDAP_ROOTDNThe distinguished name to auth againstoptional""
LDAP_PASSWORDPassword for rootdnoptional""
LDAP_FILTERSearch filter, with $user and $host substituted for user- and hostnameoptional"(uid=$user)"
LDAP_SCOPESearch scope. other values: “base” and “onelevel”optional"subtree"
LDAP_TLSEnable TLS (StartTLS) to connect to LDAP (can be true or false). The non-standard ‘LDAPS’ protocol is not supported.optional"false"
LDAP_MODEHow passwords are validated.optional"bind"
LDAP_ADMIN_FILTERSearch filter to match admins, works like ldap_filteroptional""
DB_DRIVERMay also be "PostgreSQL" or "MySQL" or "SQLite3" (case sensitive!)optionalSQLite3
DB_DATABASEThe database name to use. For SQLite3 this the database filename (relative to the data storage directory).optionalprosody.sqlite
DB_HOSTThe address of the database serveroptional
DB_PORTPort on which the database is listeningoptional
DB_USERNAMEThe username to authenticate to the databaseoptional
DB_PASSWORDThe password to authenticate to the databaseoptional
HTTP_MAX_CONTENT_SIZEMax http content size in bytesoptional10485760
HTTP_FILE_SHARE_SIZE_LIMITMax http file share size in bytesoptional10485760
HTTP_FILE_SHARE_DAILY_QUOTADaily quota in bytesoptional10 times share size limit
E2E_POLICY_CHATPolicy for chat messages. Possible values: "none", "optional" and "required".optional"required"
E2E_POLICY_MUCPolicy for MUC messages. Possible values: "none", "optional" and "required".optional"required"
E2E_POLICY_WHITELISTMake this module ignore messages sent to and from this JIDs or MUCs.optional""
LOG_LEVELMin log level. Change to debug for more informationoptionalinfo
C2S_REQUIRE_ENCRYPTIONWhether to force all client-to-server connections to be encrypted or notoptionaltrue
S2S_REQUIRE_ENCRYPTIONWhether to force all server-to-server connections to be encrypted or notoptionaltrue
S2S_SECURE_AUTHRequire encryption and certificate authenticationoptionaltrue
SERVER_CONTACT_INFO_ABUSEA list of strings. Each string should be an URI. See here.optional"xmpp:abuse@DOMAIN"
SERVER_CONTACT_INFO_ADMINA list of strings. Each string should be an URI. See here.optional"xmpp:admin@DOMAIN"
SERVER_CONTACT_INFO_FEEDBACKA list of strings. Each string should be an URI. See here.optional"xmpp:feedback@DOMAIN"
SERVER_CONTACT_INFO_SALESA list of strings. Each string should be an URI. See here.optional"xmpp:sales@DOMAIN"
SERVER_CONTACT_INFO_SECURITYA list of strings. Each string should be an URI. See here.optional"xmpp:security@DOMAIN"
SERVER_CONTACT_INFO_SUPPORTA list of strings. Each string should be an URI. See here.optional"xmpp:support@DOMAIN"
PROSODY_ADMINSSpecify who is an administrator. List of adresses. Eg. "me@example.com", "admin@example.net"optional""

DNS

You need these DNS record pointing to your server:

where domain.tld is the environment variable DOMAIN.

Extend

There is a helper script that eases installing additional prosody modules: docker-prosody-module-install

It downloads the current prosody-modules repository. The specified modules are copied and its name is added to the modules_enabled variable within conf.d/01-modules.cfg.lua.

There is also docker-prosody-module-copy which copies the specified modules but does not add them to the modules_enabled variable within conf.d/01-modules.cfg.lua.

If you need additional configuration just overwrite the respective cfg.lua file or add new ones.

Upgrade

When migrating from prosody 0.10, you need to update the database once:

docker compose exec server bash
prosodyctl mod_storage_sql upgrade

Test your server

You can test your server with these websites: