Context: The architecture of a Prose Pod
To begin with, let’s introduce you to the architecture of a Prose Pod, which will help you understand how things relate to one another.
A Prose Pod consists of four parts:
- The Prose Pod Server, running the Prosody XMPP server with additional modules for Prose requirements.
- The Prose Web application, which is a XMPP client accessible using a web browser.
- The Prose Pod API, which allows configuring the Server using a HTTP API.
- The Prose Pod Dashboard, which exposes a Web UI one can use to configure a Server, invite members, manage authorization, etc.
The bootstrapping process
For security reasons, your messaging data (stored in the Server) shouldn’t be readable by other parts of a Prose Pod. The Prose Pod API fetches data from the Server using an authenticated network interface. As a consequence, the Pod API and the Server need to share a secret to bootstrap the connection. Since it is effectively a XMPP account password, we refer to it as the “bootstrap Prose Pod API XMPP password” or “bootstrap password” for short.
To make deployments easier, we defined a default bootstrap password, but rest assured that it doesn’t make your Prose Pod less secure. As stated in Pod configuration reference > BootstrapConfig: The first thing the Prose Pod API does when starting up is changing this password to a very strong random password, so you shouldn’t have a reason to change it (see Provide a default bootstrap password · Issue #246 · prose-im/prose-pod-api).
To interact with the Server, the Pod API therefore requires it to expose certain interfaces, requiring a certain set of configuration flags to be enabled at all times. Since this is an implementation detail you shouldn’t have to worry about, we package a bootstrapping configuration in the Server image, but we don’t apply it by default (to avoid surprises on your end). Therefore, when running the proseim/prose-pod-server
image you have to change the entrypoint to sh -c "cp /usr/share/prose/prosody.bootstrap.cfg.lua /etc/prosody/prosody.cfg.lua && prosody"
. Since you will be mounting /etc/prosody
from somewhere, by knowing this you won’t be suprised if your prosody.cfg.lua
suddenly looks different in a filesystem backup.
Required files and directories
Here are all the directories a Prose Pod uses:
/var/lib/prose-pod-api/
: Pod API data (invitations, roles…)./var/lib/prosody/
: Server data (messages, avatars…)./etc/prose/
: Prose Pod configuration./etc/prosody/
: Prosody configuration (see Configuring Prosody)./etc/prosody/certs/
: SSL certificates.
/usr/share/prose/
: Bootstrapping configuration.- The Pod API image already packages this directory. Unless you want to override the bootstrapping configuration, do not mount this path in the Pod API container or your Prose Pod will fail to start.
And here are all the files you need to create and maintain:
/etc/prose/prose.toml
: See the Pod configuration reference./etc/prose/prose.env
: If using our Compose file (see Example: Compose later), this is where you can configure environment variables for your Prose Pod./etc/prosody/certs/*
: SSL certificates for your domain.
Automated deployment
To make deployments blazingly fast, we created a Bash script on get.prose.org that takes care of almost everything for you. To use it, run:
curl -L https://get.prose.org | sh
This script cannot support all scenarios, and it will skip steps or abort if it finds any blocking situation. You can try running it first, and do the rest of the deployment by hand using this guide. The main roadblocks are related to SSL certificates, which cannot be automated in some situations.
Here is an example of what it will look like (potentially outdated but it gives you an idea):
Manual deployment
Step 1: Some helper variables
To copy-paste working commands from this guide, please start by creating the following variables:
PROSE_FILES=https://raw.githubusercontent.com/prose-im/prose-pod-system/refs/heads/master
YOUR_DOMAIN= # Insert your domain
Step 2: Some DNS configuration
While the Dashboard walks you through configuring your DNS zone to get Prose working, when you are deploying a Prose Pod yourself you will need some of it in advance to get SSL certificates. While you’re at it, better add them all so this guide will provide every record you need to set.
If the machine you are deploying Prose on has static IP addresses, add the following DNS records:
; Let users connect
_xmpp-client._tcp.{your_domain}. 3600 IN SRV 0 5 5222 prose.{your_domain}.
; Access the Dashboard
admin.prose.{your_domain}. 3600 IN CNAME prose.{your_domain}.
; Required because SRV records cannot point to a CNAME
prose.{your_domain}. 3600 IN A {ipv4}
prose.{your_domain}. 3600 IN AAAA {ipv6}
; Required because we need to get a SSL certificate for `groups.{your_domain}`
groups.{your_domain}. 3600 IN CNAME prose.{your_domain}.
If you don’t have access to static IP addresses, add the following DNS records:
; Let users connect
_xmpp-client._tcp.{your_domain}. 3600 IN SRV 0 5 5222 {hostname}.
; Access the Web app
prose.{your_domain}. 3600 IN CNAME {hostname}.
; Access the Dashboard
admin.prose.{your_domain}. 3600 IN CNAME {hostname}.
; Required because we need to get a SSL certificate for `groups.{your_domain}`
groups.{your_domain}. 3600 IN CNAME {hostname}.
Step 3: Create the prose
user
For better isolation, you shouldn’t run Prose as root on your server. This guide uses a prose
user that you should create using:
# Create group
addgroup --gid 1001 prose
# Create user
adduser --uid 1001 --gid 1001 --disabled-password --no-create-home --gecos 'Prose' prose
Step 4: Create required files and directories
As detailed in “Required files and directories”, Prose Pods require a certain amount of files and directories to exist. To create them, you can run:
# Directories
install -o prose -g prose -m 750 -d \
/var/lib/{prose-pod-api,prosody} \
/etc/{prose,prosody} \
/etc/prosody/certs
# Database
install -o prose -g prose -m 640 -T /dev/null \
/var/lib/prose-pod-api/database.sqlite
# Environment
install -o prose -g prose -m 600 -T /dev/null \
/etc/prose/prose.env
Create the prose.toml
file
In order for your Prose Pod to run correctly, you need to write a few configuration keys in /etc/prose/prose.toml
.
You can find an up-to-date template at prose-im/prose-pod-system/blob/master/templates/prose.toml, or directly download it using:
# Download configuration template
curl -L "${PROSE_FILES:?}"/templates/prose.toml \
| sed s/'{your_domain}'/${YOUR_DOMAIN:?}/g \
> /etc/prose/prose.toml
# Change configuration user/group
chown prose:prose /etc/prose/prose.toml
# Then edit </etc/prose/prose.toml>!
Once done, edit the file to replace all placeholders with your company information.
SSL certificates
To run a Prose Pod, the messaging server will need certificates for {your_domain}
and groups.{your_domain}
. If you don’t already have those, here is one way to get them:
Install certbot:
apt update apt install -y certbot
Ensure you have DNS records pointing
{your_domain}
andgroups.{your_domain}
to your server (so certbot can pass its SSL challenge). If you don’t have it, go back to Step 2: Some DNS configuration.Request a SSL certificate for your Prose Pod:
certbot certonly --standalone -d ${YOUR_DOMAIN:?} -d groups.${YOUR_DOMAIN:?}
Note that certbot should have automatically created
/etc/cron.d/certbot
to handle certificates renewal.Click to show an example
/etc/cron.d/certbot
# /etc/cron.d/certbot: crontab entries for the certbot package # # Upstream recommends attempting renewal twice a day # # Eventually, this will be an opportunity to validate certificates # haven't been revoked, etc. Renewal will only occur if expiration # is within 30 days. # # Important Note! This cronjob will NOT be executed if you are # running systemd as your init system. If you are running systemd, # the cronjob.timer function takes precedence over this cronjob. For # more details, see the systemd.timer manpage, or use systemctl show # certbot.timer. SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew --no-random-sleep-on-renew
certbot certificates are stored in
/etc/letsencrypt/live
, but Prosody will search in/etc/prosody/certs
. Normally we’d useprosodyctl --root cert import /etc/letsencrypt/live
(as explained in Let’s Encrypt – Prosody IM), but Prose runs Prosody in a dedicated container therefore your server doesn’t have access toprosodyctl
(and we can’t use symbolic links). Here is one way to copy the certificates manually:rsync -aL --chown=prose:prose /etc/{letsencrypt/live,prosody/certs}/${YOUR_DOMAIN:?}/
certbot should have automatically created
/etc/cron.d/certbot
to handle certificates renewal, but you still have to add a certbot renewal hook to update Prosody certificates when certificates are renewed. For this, assign the command you executed previously in aspost_hook
under[renewalparams]
in/etc/letsencrypt/renewal/${YOUR_DOMAIN:?}.conf
. For example, if you usedrsync -aL --chown=prose:prose /etc/{letsencrypt/live,prosody/certs}/${YOUR_DOMAIN:?}/
you should set:post_hook = "/bin/bash -c 'rsync -aL --chown=prose:prose /etc/{letsencrypt/live,prosody/certs}/{your_domain}/'"
Make sure to replace{your_domain}
by your domain!
Step 5: Run your Prose Pod
To run a Prose Pod on your premises, you have to run all of its parts independently. Each is released as a Docker image, on Docker Hub (see hub.docker.com/u/proseim) and on GitHub’s Container Registry (see github.com/orgs/prose-im/packages).
Example: Run with Docker Compose
To make deployments and updates easier, we maintain a Compose file in prose-im/prose-pod-system.
If you want to use Docker Compose to deploy a Prose Pod, here are the steps you need to follow:
Ensure you have Docker and Docker Compose installed and operational.
Tip: If you don’t have it already, the easiest way to install Docker is to runcurl -L https://get.docker.com | sh
.Add the
prose
user to thedocker
group:usermod -aG docker prose
Get the latest Compose file using:
# Download Docker Compose file curl -L "${PROSE_FILES:?}"/compose.yaml -o /etc/prose/compose.yaml # Change Compose file user/group chown prose:prose /etc/prose/compose.yaml
Configure systemd to run Prose at startup and run it:
# Install systemd service file curl -L "${PROSE_FILES:?}"/templates/prose.service -o /etc/systemd/system/prose.service # Enable the prose systemd service systemctl daemon-reload systemctl enable prose systemctl start prose
While systemctl start prose
should have failed if something was wrong, you can still run the following command to make sure every part of your Prose Pod is running (you should see an empty table, with headers only):
docker compose -f /etc/prose/compose.yaml ps --status=exited
If you see one that has exited, check its logs using:
docker compose -f /etc/prose/compose.yaml logs --no-log-prefix -- {service_name}
Step 6: Configure the reverse proxy
The traffic to your Prose Pod will need to be routed by a reverse proxy.
apt install -y nginx python3-certbot-nginx
certbot certonly --nginx -d prose.${YOUR_DOMAIN:?} -d admin.prose.${YOUR_DOMAIN:?}
To make deployments easier, we maintain a NGINX configuration file at templates/nginx.conf in github.com/prose-im/prose-pod-system. You can download and enable it using:
# Install NGINX files
curl -L "${PROSE_FILES:?}"/templates/nginx.conf \
| sed s/'{your_domain}'/${YOUR_DOMAIN:?}/g \
> /etc/nginx/sites-available/prose.${YOUR_DOMAIN:?}
# Enable NGINX sites
ln -s /etc/nginx/sites-{available,enabled}/prose.${YOUR_DOMAIN:?}
# Disable the catch-all default NGINX configuration
rm /etc/nginx/sites-enabled/default
# Apply the new NGINX configuration
systemctl reload nginx
Step 7: .well-known/host-meta
WWW_ROOT=/var/www/default
mkdir -p "${WWW_ROOT:?}"/.well-known/
# .well-known/host-meta (XML)
curl -L "${PROSE_FILES:?}"/templates/host-meta \
| sed s/'{your_domain}'/${YOUR_DOMAIN:?}/g \
> "${WWW_ROOT:?}"/.well-known/host-meta
# .well-known/host-meta.json
curl -L "${PROSE_FILES:?}"/templates/host-meta.json \
| sed s/'{your_domain}'/${YOUR_DOMAIN:?}/g \
> "${WWW_ROOT:?}"/.well-known/host-meta.json
# Install NGINX files
curl -L "${PROSE_FILES:?}"/templates/nginx-well-known.conf \
| sed s/'{your_domain}'/${YOUR_DOMAIN:?}/g \
> /etc/nginx/sites-available/${YOUR_DOMAIN:?}
# Enable NGINX sites
ln -s /etc/nginx/sites-{available,enabled}/${YOUR_DOMAIN:?}
# Apply the new NGINX configuration
systemctl reload nginx
Step 8: Check that your Prose Pod is running correctly
If you have a Web browser, you can check that your Prose Pod has started successfully by opening the Dashboard at http://localhost:8081
.
Otherwise, you can run:
curl http://localhost:8081/api/pod/version
If you get a JSON payload back containing information about the versions of you Prose Pod’s components, it means everything should be working correctly. If you want to make sure everything is well configured or if the call fails, you will have to check the logs.
Checking logs using Docker Compose
To check for errors or warnings using Docker Compose, you can run:
docker compose -f /etc/prose/compose.yaml logs | grep -i -e 'error|warn'
If you don’t see the problem or are missing context, you should check all the logs using:
docker compose -f /etc/prose/compose.yaml logs
If the logs you see still don’t guide you to a solution, reach out to our technical support team which will gladly help you fix any issue you encounter.
Step 9: Initializing your Prose Pod
Now that your Prose Pod is running, you need to create the first admin account, configure your DNS records and invite your first colleague. All of this can be done using the administration Dashboard which is accessible at http://localhost:8081
.
However, you very likely don’t have access to a web browser on the machine where you are running the Prose Pod so you will have to create a first DNS record in order for you to access the Dashboard from your own web browser.
If your server has a public IP address, add the following records to your DNS zone (replacing {ipv4}
and {ipv6}
by your server’s IPv4 and IPv6 addresses):
admin.prose 10800 IN A {ipv4}
admin.prose 10800 IN AAAA {ipv6}
If your server is already accessible via a hostname, add this CNAME
record to your DNS zone instead (replacing {hostname}
by your server’s public hostname):
prose 10800 IN CNAME {hostname}
prose
to something else, it’s not hard-coded anywhere on our side, but beware that our guides will assume you used this value so you’ll have to change it everywhere we mention prose.{your_domain}
.Now, or after a few minutes (for your DNS provider to propagate the new records), you should be able to open https://prose.{your_domain}:8081
in your web browser and see your Prose Pod Dashboard. If you get a SSL error, go back to the “SSL certificates” section and make sure everything is correct.
Now that you have access to your Dashboard, you can follow the “Initializing your workspace” section of the “Quickstart” guide to finish configuring your Prose Pod.