Files
prosody/docker-compose.yml
mguschin 3fc1ac3d12 Add TURN/STUN server for audio/video calls.
Jingle A/V (XEP-0166/0167/0176) needs a STUN/TURN server for NAT
traversal. Add coturn and advertise it to clients via XEP-0215.

- coturn container, host networking (a relay needs its full UDP port
  range reachable, and Docker NAT hides the peer addresses coturn needs).
- mod_turn_external in Prosody to advertise the service and mint
  time-limited credentials from a shared secret.
- Advertise UDP and TCP transports plus turns: on 5349, so clients on
  UDP-blocking networks can still connect.
- Deny relaying to private ranges, so this is not an open proxy into
  internal services.

TURN host is guschin.info rather than turn.guschin.info because only the
former is in the certificate SANs and turns: clients validate the name.

TURN_HOST/TURN_SECRET go in .env, which is gitignored and set per
deployment; TURN_SECRET must match static-auth-secret in turnserver.conf.

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

81 lines
2.6 KiB
YAML

services:
prosody:
build:
context: .
dockerfile: Dockerfile
container_name: prosody-xmpp
environment:
XMPP_DOMAIN: ${XMPP_DOMAIN}
XMPP_USER: ${XMPP_USER}
XMPP_PASSWORD: ${XMPP_PASSWORD}
MYSQL_HOST: ${MYSQL_HOST:-host.docker.internal}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
SLIDGRAM_COMPONENT_SECRET: ${SLIDGRAM_COMPONENT_SECRET}
TURN_HOST: ${TURN_HOST}
TURN_SECRET: ${TURN_SECRET}
extra_hosts:
- "host.docker.internal:172.17.0.1"
ports:
- "5222:5222"
- "5269:5269"
- "5280:5280"
- "5281:5281"
volumes:
- ./data/prosody:/var/lib/prosody
- ./logs/prosody:/var/log/prosody
- ./data/prosody/configuration:/etc/prosody/conf.d
- /etc/letsencrypt/live/xmpp.guschin.info:/etc/prosody/certs/letsencrypt/live/xmpp.guschin.info:ro
- /etc/letsencrypt/archive/xmpp.guschin.info:/etc/prosody/certs/letsencrypt/archive/xmpp.guschin.info:ro
- /etc/letsencrypt/live/guschin.info:/etc/prosody/certs/letsencrypt/live/guschin.info:ro
- /etc/letsencrypt/archive/guschin.info:/etc/prosody/certs/letsencrypt/archive/guschin.info:ro
restart: unless-stopped
mem_limit: 200M
healthcheck:
test: ["CMD", "nc", "-z", "localhost", "5222"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- prosody
slidgram:
image: codeberg.org/slidge/slidgram:latest
container_name: slidgram
user: "100:102"
environment:
SLIDGE_JID: telegram.guschin.info
SLIDGE_SECRET: ${SLIDGRAM_COMPONENT_SECRET}
SLIDGE_SERVER: prosody-xmpp
SLIDGE_PORT: 5347
SLIDGE_UPLOAD_SERVICE: upload.guschin.info
volumes:
- ./data/slidgram:/var/lib/slidge
restart: unless-stopped
depends_on:
prosody:
condition: service_healthy
networks:
- prosody
coturn:
image: coturn/coturn:4.6-alpine
container_name: coturn
# Host networking: a TURN relay needs its whole UDP port range reachable,
# and Docker's userland NAT both mangles the source addresses coturn needs
# to see and makes publishing the range impractical.
network_mode: host
volumes:
- ./coturn/turnserver.conf:/etc/coturn/turnserver.conf:ro
- /etc/letsencrypt/live/guschin.info:/etc/coturn/certs:ro
- /etc/letsencrypt/archive/guschin.info:/etc/letsencrypt/archive/guschin.info:ro
command: ["-c", "/etc/coturn/turnserver.conf"]
restart: unless-stopped
mem_limit: 128M
networks:
prosody:
driver: bridge