# The server, the TLS proxy and the TURN relay. This file is not edited: whatever # differs between installs lives in .env — usually a single line, DOMAIN. services: app: image: ghcr.io/frum1/justcall-server:latest # build: . # build from source locally instead of pulling the image container_name: justcall restart: unless-stopped env_file: .env environment: # The port is not published: only caddy reaches the server, over the # internal network. BIND_ADDR: 0.0.0.0:8080 USERS_DB: /data/users.db RUST_LOG: ${RUST_LOG:-info} volumes: # users.db. Backup: docker compose cp app:/data/users.db ./users.db.bak - data:/data networks: - internal caddy: image: caddy:2-alpine container_name: justcall-caddy restart: unless-stopped depends_on: - app environment: DOMAIN: ${DOMAIN:?set DOMAIN in .env — the server domain, e.g. call.example.com} ports: - "80:80" - "443:443" - "443:443/udp" # HTTP/3 volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config networks: - internal coturn: image: coturn/coturn:4 container_name: justcall-coturn restart: unless-stopped # Host networking, because of the relay port range: publishing forty UDP # ports one by one through docker-proxy is both slow and pointless. network_mode: host # There is no separate turnserver.conf: the domain and the secret already # live in .env, and a second file holding a copy of the secret used to drift # from it silently. `-n` = do not look for a config file. command: - -n - --log-file=stdout - --external-ip=$$(detect-external-ip) - --listening-port=3478 - --fingerprint - --use-auth-secret - --static-auth-secret=${TURN_SECRET:?TURN_SECRET is not set in .env — generate one (see the README)} - --realm=${DOMAIN} # Where relaying is FORBIDDEN. Without these lines the credentials handed # out are a way into the local network: in a cloud, 169.254.169.254 serves # the instance credentials. - --denied-peer-ip=0.0.0.0-0.255.255.255 - --denied-peer-ip=10.0.0.0-10.255.255.255 - --denied-peer-ip=127.0.0.0-127.255.255.255 - --denied-peer-ip=169.254.0.0-169.254.255.255 - --denied-peer-ip=172.16.0.0-172.31.255.255 - --denied-peer-ip=192.168.0.0-192.168.255.255 - --denied-peer-ip=224.0.0.0-255.255.255.255 - --denied-peer-ip=::1 - --denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff - --denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff - --no-multicast-peers - --no-tcp-relay # Ceilings, so the relay does not become free transit. - --total-quota=100 - --user-quota=6 - --max-bps=256000 # The relay port range — the reason this container lives on the host network. - --min-port=49160 - --max-port=49200 networks: internal: volumes: data: caddy_data: caddy_config: