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 (environment)./etc/prose-pod-api/
: Pod API 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-pod-api/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.
Deployment steps
Step 1: A helper variable
To copy-paste working commands from this guide, you should start by storing your domain as YOUR_DOMAIN
:
YOUR_DOMAIN= # Insert your domain
Step 2: 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 3: 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,prose-pod-api,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-pod-api/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 https://raw.githubusercontent.com/prose-im/prose-pod-system/refs/heads/master/templates/Prose.toml \
| sed s/'{your_domain}'/"${YOUR_DOMAIN:?}"/g \
> /etc/prose-pod-api/Prose.toml
# Change configuration user/group
chown prose:prose /etc/prose-pod-api/Prose.toml
# Then edit </etc/prose-pod-api/Prose.toml>!
Once done, edit the file to replace all placeholders with your company information.
SSL certificates
apt install -y nginx
.Install certbot:
apt install -y certbot python3-certbot-nginx
Ensure you have
A
/AAAA
DNS records pointing to your server (so certbot can pass its SSL challenge).Request a SSL certificate for your Prose Pod:
certbot --nginx \ -d prose.${YOUR_DOMAIN:?} \ -d admin.prose.${YOUR_DOMAIN:?} \ -d groups.prose.${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}/
Tip: If you manage multiple certificates and want Prosody to only see the one you use for Prose, you can usersync -aL --chown=prose:prose /etc/{letsencrypt/live,prosody/certs}/${YOUR_DOMAIN:?}/
instead.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/prose.${YOUR_DOMAIN:?}.conf
. For example, if you usedrsync -aL --chown=prose:prose /etc/{letsencrypt/live,prosody/certs}/
you should set:post_hook = "/bin/bash -c 'rsync -aL --chown=prose:prose /etc/{letsencrypt/live,prosody/certs}/'"
Step 3: 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 https://raw.githubusercontent.com/prose-im/prose-pod-system/refs/heads/master/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 https://raw.githubusercontent.com/prose-im/prose-pod-system/refs/heads/master/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 4: Configure the reverse proxy
The traffic to your Prose Pod will need to be routed by a reverse proxy.
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 https://raw.githubusercontent.com/prose-im/prose-pod-system/refs/heads/master/templates/nginx.conf \
| sed s/'{your_domain}'/"${YOUR_DOMAIN:?}"/g \
> /etc/nginx/sites-available/prose."${YOUR_DOMAIN:?}"
# Create symbolic links to NGINX files (enable sites)
ln -s /etc/nginx/sites-{available,enabled}/prose."${YOUR_DOMAIN:?}"
systemctl reload nginx
Step 5: .well-known/host-meta
mkdir -p /var/www/default/.well-known/
# .well-known/host-meta (XML)
curl -L https://raw.githubusercontent.com/prose-im/prose-pod-system/refs/heads/master/templates/host-meta \
| sed s/'{your_domain}'/"${YOUR_DOMAIN:?}"/g \
> /var/www/default/.well-known/host-meta
# .well-known/host-meta.json
curl -L https://raw.githubusercontent.com/prose-im/prose-pod-system/refs/heads/master/templates/host-meta.json \
| sed s/'{your_domain}'/"${YOUR_DOMAIN:?}"/g \
> /var/www/default/.well-known/host-meta.json
If your server is the one serving your domain and you don’t have a certificate just yet, run:
certbot --nginx -d ${YOUR_DOMAIN:?}
# Install NGINX files
curl -L https://raw.githubusercontent.com/prose-im/prose-pod-system/refs/heads/master/templates/nginx-well-known.conf \
| sed s/'{your_domain}'/"${YOUR_DOMAIN:?}"/g \
> /etc/nginx/sites-available/"${YOUR_DOMAIN:?}"
# Create symbolic links to NGINX files (enable sites)
ln -s /etc/nginx/sites-{available,enabled}/"${YOUR_DOMAIN:?}"
systemctl reload nginx
Step 6: 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:3030
.
Otherwise, you can run:
curl http://localhost:3030/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 7: 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:3030
.
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}:3030
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.