Files
prosody/README.md
mguschin c11f05481c Fix coturn TLS listeners and pin relay to public IP.
Two problems found once coturn was running:

TLS listeners never started. The live/ certificate files are relative
symlinks into ../../archive/, so mounting live/ alone left them dangling
and coturn silently fell back to no TLS, disabling turns: on 5349.
Prosody's identical mount works only because its entrypoint copies the
files; coturn reads them in place. Mount both trees at their real paths
and reference the cert through live/.

Relay used every interface. Without explicit addresses coturn discovered
all of them and offered relay candidates on the Docker bridges and
loopback -- unreachable for remote peers, and needless exposure of the
internal networks. Pin listening-ip and relay-ip to the public address.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 22:20:37 +03:00

147 lines
4.7 KiB
Markdown

# Prosody XMPP Server
Dockerized Prosody XMPP server with MySQL backend.
## Prerequisites
- Docker and Docker Compose
- External MySQL network: `mysqlgit_mysql_network`
- Environment variables configuration (see Configuration section)
## Configuration
This setup uses environment variables for configuration. Create a `.env` file in the project root with:
```env
# XMPP Configuration
XMPP_DOMAIN=xmpp.guschin.info
XMPP_USER=mish
XMPP_PASSWORD=your_password
# MySQL Configuration
MYSQL_HOST=mysql
MYSQL_USER=prosody
MYSQL_PASSWORD=your_mysql_password
MYSQL_DATABASE=prosody
```
## Starting the Server
Run from the project directory:
```bash
docker-compose up -d
```
This will:
- Build and start the Prosody container
- Connect to external MySQL network (`mysqlgit_mysql_network`)
- Wait for MySQL to be ready
- Generate self-signed SSL/TLS certificates (if not present)
- Configure Prosody with MySQL backend
## Access Points
| Service | Port | Description |
|---------|------|-------------|
| C2S (Client to Server) | 5222 | XMPP client connections |
| S2S (Server to Server) | 5269 | XMPP federation |
| Component Protocol | 5347 | External components |
| HTTP/BOSH/WebSocket | 5280 | Web-based connections |
| HTTPS | 5281 | Secure web connections |
| STUN/TURN | 3478 (UDP+TCP) | NAT traversal for audio/video calls |
| STUN/TURN over TLS | 5349 (UDP+TCP) | Encrypted TURN (`turns:`) |
| TURN relay range | 49160-49200 (UDP) | Media relay ports |
## Features
- **Virtual Host**: `xmpp.guschin.info`
- **Multi-User Chat (MUC)**: `muc.xmpp.guschin.info`
- **Storage**: MySQL backend with SQL storage
- **Admin User**: `admin@guschin.info`
- **Health Checks**: Automatic container health monitoring
- **Memory Limit**: 200M
- **Auto-restart**: Container restarts unless stopped
## Enabled Modules
Core modules: roster, saslauth, tls, dialback, disco, carbons, pep, private, blocking, vcard, version, uptime, time, ping, register, last_activity, admin_adhoc, muc_mam
## Data Persistence
Volumes are mounted to persist data:
- `./data/prosody``/var/lib/prosody`
- `./logs/prosody``/var/log/prosody`
- `./data/prosody/configuration``/etc/prosody/conf.d`
## Connecting Clients
Use any XMPP client with:
- **Server**: xmpp.guschin.info
- **Port**: 5222
- **Username**: your configured user
- **Domain**: xmpp.guschin.info
## Audio/Video Calls (Jingle)
Voice and video calls use Jingle (XEP-0166/0167/0176). Prosody only carries the
signalling; media flows directly between clients, falling back to a TURN relay
when NAT prevents a direct path.
Two pieces make this work:
- **coturn** (`coturn` container) — the STUN/TURN server. Runs with host
networking because a relay needs its whole UDP port range reachable.
- **`mod_turn_external`** in Prosody — advertises coturn to clients over
XEP-0215 and issues time-limited TURN credentials.
### Configuration
`TURN_SECRET` in `.env` must match `static-auth-secret` in
[coturn/turnserver.conf](coturn/turnserver.conf). `.env` is gitignored, so
these values are set per-deployment and not committed:
```env
TURN_HOST=guschin.info
TURN_SECRET=<same value as static-auth-secret>
```
`TURN_HOST` is `guschin.info`, not `turn.guschin.info`: `turns:` (TLS) clients
validate the hostname against the certificate, and only `guschin.info` is in
the current cert's SANs. To use `turn.guschin.info` instead, reissue the
certificate with that name added and update both `TURN_HOST` and the
`external-ip`/`cert` settings accordingly.
`turnserver.conf` pins the server's public address in three places:
`listening-ip`, `relay-ip`, and `external-ip`. **Update all three if the
server IP changes**, otherwise coturn advertises relay candidates that peers
cannot reach. Pinning them also stops coturn from auto-discovering the Docker
bridge interfaces and relaying on unreachable private addresses.
### Verifying
Check that Prosody advertises the service and coturn answers:
```bash
docker logs coturn # should show listeners on 3478/5349
docker exec prosody-xmpp prosodyctl check config
```
From a client, place a call between two accounts. Clients that support Jingle
audio/video include Conversations (Android), Dino, Gajim, and Monal (iOS).
Note that Jingle A/V is client-to-client — both parties need a client that
supports it.
### Firewall
Ports 3478 and 5349 (both UDP and TCP) plus the UDP relay range 49160-49200
must be reachable from the internet. The host has no local firewall
(`iptables` INPUT policy is ACCEPT), but any provider-level firewall needs
these opened.
## Notes
- TLS encryption is not required by default (configurable in [prosody.cfg.lua](data/prosody/configuration/prosody.cfg.lua))
- Self-signed certificates are auto-generated on first run
- The container depends on an external MySQL network named `mysqlgit_mysql_network`