services: livekit: # Fix Docker Swarm's docker-proxy source address mangling on the TURN # relay → SFU path. Two fixes are applied: # # 1. Add NODE_IP to the first non-loopback interface so the kernel # delivers relay→SFU packets locally (via loopback) instead of # routing through docker-proxy. # # 2. SNAT SFU responses so the source address matches NODE_IP. # pion/ice may select a different socket (overlay IP) for responses, # which would fail TURN permission checks. The iptables rule ensures # all responses to relay ports come from NODE_IP. cap_add: - NET_ADMIN entrypoint: ["/bin/sh", "-c"] command: - | IFACE=$$(ls /sys/class/net/ | grep -v lo | head -1) ip addr add $$LIVEKIT_NODE_IP/32 dev $$IFACE 2>/dev/null || true apk add --no-cache iptables >/dev/null 2>&1 iptables -t nat -A POSTROUTING -p udp --sport 7882 -d $$LIVEKIT_NODE_IP -j SNAT --to-source $$LIVEKIT_NODE_IP exec /livekit-server --config /livekit-server.yaml ports: - target: 443 published: 443 protocol: udp mode: host # TURN relay ports — each concurrent TURN user needs ~3 relay ports. - target: 30000 published: 30000 protocol: udp mode: host - target: 30001 published: 30001 protocol: udp mode: host - target: 30002 published: 30002 protocol: udp mode: host - target: 30003 published: 30003 protocol: udp mode: host - target: 30004 published: 30004 protocol: udp mode: host - target: 30005 published: 30005 protocol: udp mode: host - target: 30006 published: 30006 protocol: udp mode: host - target: 30007 published: 30007 protocol: udp mode: host - target: 30008 published: 30008 protocol: udp mode: host - target: 30009 published: 30009 protocol: udp mode: host