XMPP Server - Prosody
-
Big update - I'm ready for your help @girish .
Repo: https://github.com/DerekJarvis/cloudron-prosody
Docker Image: derekjarvis/cloudron-prosody:20250406-042328-86345387dWhat's working:
Everything.
This is a full-fledged XMPP server with:
- Healthcheck
- TURN server for jingle calling (voice and video)
- Uses LDAP for auth and automatically works for all users
- Supports sending/receiving files and images
- Supports message carbons (sync messages between devices)
- Supports standard (pretty) accounts like user@domain.com
(Direct TLS failing is intentional because it's deprecated and our upstream doesn't bother supporting it)Approach:
I forked from a repository that has a good Prosody docker image with VERY secure defaults. I actually had to loosen a couple to make it more user friendly (like not requiring OMEMO). I added on the modules that make it even more useful (like HTTP upload for file attachments, TURN for jingle calls). I tried to make the majority of changes in our own files to make it easier to compare to upstream. I used Cloudron services (like LDAP, TURN) instead of running extra services in the container.
Help Needed:
There are a few VERY hacky things I had to do to make this work. Only one is a total blocker for real deployment by others, the others are all "nice to have" improvements.
TLD (Top-Level Domain) certs (blocker)
XMPP needs the TLD cert to allow the standard (and pretty) usernames like
user@domain.com
. Right now, there's no way for a Cloudron app to request the TLD cert. To work around this I did the following:- Made a storage volume for the app
- Copied all the certs into the storage volume (yes, this is a very bad idea)
cp -f /home/yellowtent/platformdata/nginx/cert/* /mnt/HC_Volume_102134826/app_xmpp/
- Have the app use the certs it needs and then delete everything else
Aliases needed (nice to have)
The app is installed under the "xmpp" domain, and 4 aliases must be defined in the app, and also in the DNS records:
It would be great if the Manifest allowed us to specify additional aliases the app needs, and also added the DNS records for those if the Cloudron instance is using a DNS API
SRV Records (nice to have)
XMPP uses SRV records to give information about the XMPP servers for a domain. Specifically:
- _xmpp-client._tcp.domain.tld port 5222
- _xmpps-client._tcp.domain.tld port 5223
- _xmpp-server._tcp.domain.tld port 5269
Add these manually, and your app will work fine.
It would be ideal if Cloudron allowed specifying additional DNS records that should be created if the Cloudron instance is using a DNS API.
Admin users (nice to have)
I couldn't find a way to identify Cloudron Admin users through LDAP. Prosody supports specifying an LDAP query to indicate who is an admin of the XMPP server.
It would be ideal if there was an LDAP query that could identify Admin users, and then Prosody would mark those users as admins as well.
External IP for checks (nice to have)
Prosody has a very convenient
check
function which will check for common errors. One of the things it checks for is if it thinks it is reachable by checking the DNS records it uses against the IP addresses it knows it has. So in the Prosody config you can tell it the known IP addresses for the server, and thecheck
function will compare that to the DNS records to confirm the server is reachable.It would be ideal if we have an environment variable for the server's primary IP address. With this the checks would not show so many false positives.
TLD environment variable (nice to have)
Prosody needs to know the TLD it is serving. I did not find an environment variable for this, so I hacked one using bash:
export DOMAIN=${CLOUDRON_WEBADMIN_ORIGIN#https://my.}
It would be ideal if Cloudron exposed an environment variable for the TLD.
Other Comments
The #1 reason I use XMPP is for self-hosted private chat. The #2 reason is it's how I have a virtual phone number for SMS. I use https://jmp.chat to get a VERY CHEAP sms number and use XMPP on all my devices to communicate with people through SMS on convenient chat apps like Gajim and Conversations.
-
@djxx very nice! I just tried to quickly test this and building from your repo, the app fails to start with the following error:
cp: cannot stat '/media/Extra Storage/app_xmpp/*': No such file or directory
probably some oversight there, but don't have time to dig into this just now.
-
@djxx very nice! I just tried to quickly test this and building from your repo, the app fails to start with the following error:
cp: cannot stat '/media/Extra Storage/app_xmpp/*': No such file or directory
probably some oversight there, but don't have time to dig into this just now.
@nebulon - Correct. You would need to make a volume called "Extra Storage", mount it onto the app, and have a folder under it called app_xmpp where you copy the sub-domain and TLD certs you need (I just copied all of them). This is an ugly workaround for the TLD cert not being available to the app through the manifest configuration.
You would also need to add a few alias domains and DNS records manually.
-
I guess some clear set up instructions would help
- install the app to the 'xmpp' subdomain
- add extra DNS CNAME/A records pointing to the same server:
- pubsub
- proxy
- upload
- conference
- add these domains as aliases for the app
- add DNS SRV records:
- _xmpp-client._tcp.domain.tld port 5222
- _xmpps-client._tcp.domain.tld port 5223
- _xmpp-server._tcp.domain.tld port 5269
- make a storage volume called "Extra Storage"
- mount the storage volume to the app
- copy certs into the storage under the subdirectory app_xmpp
- for my server, the command looks like this (run in cloudron directly, not in the app terminal):
cp -f /home/yellowtent/platformdata/nginx/cert/* /mnt/HC_Volume_102134826/app_xmpp/
- restart the app to make sure it's starting up with all pieces in place (extra domains, DNS records, and certs)
Then you can check for compliance with these two tools:
-
I took the time to take a bit closer into the package. There is a long way to go to make it compliant with Cloudron packaging. It is a great start and we don't provide good information on what is expected from Cloudron packages, so this is mostly our fault.
For a start, you already added the
tls
addon, which does provide the certs in/etc/certs/
using that instead of the extra volume mount will ensure the app gets restarted and will pick up the correct certs if they get renewed. I am playing a bit from your package to hopefully get this working.One question is, apparently certs for the root domain are also required, even though no DNS records for that are? This can be solved by also adding the root domain as an alias to the app.
For the extra required DNS records, we have to see if and how we can integrate this in the platform to support those. We already have some well-known type records, maybe it fits there.
Otherwise there are naturally discrepancies elsewhere, given that this started (as far as I can tell) from some upstream Dockerimage which will not fit, but we can get through one by one. The first I noticed was, that currently it doesn't work with the Cloudron app debug mode, since it uses
ENTRYPOINT
in Dockerfile, that was easy to change by relying only onCMD