Files
easy-asterisk/docker-compose.yml
T
Claude 8934d71391 Add full TURN relay support for reliable calls from any network
Problem: Calls via FQDN work "sometimes" because STUN-only mode fails
behind strict NAT (cellular, Proton VPN, hotel WiFi, corporate firewalls).
STUN tells clients their public IP, but can't relay media when direct
UDP paths are blocked. TURN relays media as a fallback.

Changes:

coturn (docker-compose.yml):
- Upgraded from STUN-only to full STUN+TURN relay
- Uses long-term credential mechanism (--lt-cred-mech)
- Credentials shared between coturn and Asterisk automatically
- Relay port range 49152-49252 (configurable, ~50 concurrent relayed calls)
- Always-on (removed --profile stun gate)
- Conditional --external-ip (only set when PUBLIC_IP is provided)

Entrypoint (docker/entrypoint.sh):
- Auto-detects public IP (ifconfig.me → icanhazip.com → api.ipify.org)
- Auto-generates TURN password on first startup (saved to config)
- Configures rtp.conf with icesupport + stunaddr + turnaddr + credentials
- Updates pjsip.conf external_*_address if public IP changes
- Always enables ICE, STUN, and TURN for Docker deployments

Main script (easy-asterisk-v0.10.0.sh):
- Added TURN_ENABLED, TURN_SERVER, TURN_USERNAME, TURN_PASSWORD to
  load_config/save_config
- repair_core_configs: rtp.conf now includes turnaddr/turnusername/turnpassword
  when TURN is enabled
- Bash device creation: Docker mode defaults to FQDN (TLS) for all new devices
- Python device creation: reads TURN_ENABLED, auto-selects FQDN in Docker
- Main menu shows TURN status

.env.example:
- Comprehensive documentation for every setting
- DOMAIN_NAME is the only required setting
- Port forwarding requirements clearly listed
- TURN credentials and relay port range documented

The result: `docker compose up -d` gives you a fully working PBX where
any SIP client on any network can connect reliably via FQDN:5061.

https://claude.ai/code/session_01Vm6NLaQuzM4VosAotqS1q8
2026-02-21 16:09:50 +00:00

115 lines
4.1 KiB
YAML

# ================================================================
# Easy Asterisk - Docker Compose
#
# Usage:
# docker compose up -d # Start everything
# docker exec -it easy-asterisk easy-asterisk # Interactive management
# docker exec -it easy-asterisk vpn-diagnostics # VPN diagnostics
#
# All clients connect via FQDN (TLS) regardless of their network.
# coturn provides STUN (NAT detection) + TURN (media relay) so calls
# work even behind strict firewalls, cellular NAT, or VPNs like Proton.
# ================================================================
services:
# ── Asterisk PBX ───────────────────────────────────────────
asterisk:
build: .
container_name: easy-asterisk
# Host networking required for:
# - RTP media ports (10000-20000 UDP) - too many to map individually
# - Proper NAT detection and SIP Contact headers
# - Direct access to coturn on localhost
network_mode: host
depends_on:
coturn:
condition: service_healthy
volumes:
- asterisk-config:/etc/asterisk
- easy-asterisk-config:/etc/easy-asterisk
- asterisk-logs:/var/log/asterisk
- asterisk-spool:/var/spool/asterisk
- asterisk-lib:/var/lib/asterisk
environment:
# ── Domain (REQUIRED for remote access) ──
# Your FQDN that points to this server's public IP
- DOMAIN_NAME=${DOMAIN_NAME:?Set DOMAIN_NAME in .env}
- ENABLE_TLS=${ENABLE_TLS:-y}
# ── Public IP ──
# Auto-detected if empty. Set manually if detection fails.
- PUBLIC_IP=${PUBLIC_IP:-}
# ── Local Network ──
- LOCAL_CIDR=${LOCAL_CIDR:-}
# ── Additional Subnets ──
# Space-separated CIDRs for VLANs, site-to-site VPNs, etc.
# NOT needed for client-side VPNs (Proton, NordVPN) - TURN handles those
- HAS_VLANS=${HAS_VLANS:-n}
- VLAN_SUBNETS=${VLAN_SUBNETS:-}
# ── TURN/STUN Server ──
# Points to the coturn service (auto-configured)
- TURN_ENABLED=y
- TURN_SERVER=${DOMAIN_NAME:?}:3478
- TURN_USERNAME=${TURN_USERNAME:-easyasterisk}
- TURN_PASSWORD=${TURN_PASSWORD:-}
# ── RTP Port Range ──
- RTP_START=${RTP_START:-10000}
- RTP_END=${RTP_END:-20000}
# ── Web Admin ──
- WEB_ADMIN_PORT=${WEB_ADMIN_PORT:-8080}
- WEB_ADMIN_AUTH_DISABLED=${WEB_ADMIN_AUTH_DISABLED:-false}
restart: unless-stopped
healthcheck:
test: ["CMD", "asterisk", "-rx", "core show version"]
interval: 30s
timeout: 5s
retries: 3
# ── TURN/STUN Relay Server (coturn) ──────────────────────────
# Provides:
# STUN - Tells clients their public IP (NAT detection)
# TURN - Relays media when direct UDP paths are blocked
# (corporate firewalls, cellular NAT, Proton VPN, etc.)
#
# Without TURN, calls work "sometimes" - with TURN, they always work.
coturn:
image: coturn/coturn:latest
container_name: easy-asterisk-coturn
network_mode: host
entrypoint: ["/bin/sh", "-c"]
command:
- |
# Build coturn arguments
ARGS="-n --listening-port=3478 --fingerprint --lt-cred-mech"
ARGS="$$ARGS --user=${TURN_USERNAME:-easyasterisk}:${TURN_PASSWORD:-changeme}"
ARGS="$$ARGS --realm=${DOMAIN_NAME:-localhost}"
ARGS="$$ARGS --min-port=${TURN_RELAY_MIN:-49152}"
ARGS="$$ARGS --max-port=${TURN_RELAY_MAX:-49252}"
# Only add external-ip if PUBLIC_IP is set
if [ -n "${PUBLIC_IP:-}" ]; then
ARGS="$$ARGS --external-ip=${PUBLIC_IP}"
fi
ARGS="$$ARGS --no-tls --no-dtls --no-cli"
ARGS="$$ARGS --no-multicast-peers --no-loopback-peers"
ARGS="$$ARGS --log-file=stdout"
exec turnserver $$ARGS
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "ss -uln | grep -q ':3478'"]
interval: 30s
timeout: 5s
retries: 3
volumes:
asterisk-config:
easy-asterisk-config:
asterisk-logs:
asterisk-spool:
asterisk-lib: