quaint-kitchen-99447
03/25/2026, 7:25 PMtall-airline-16756
03/25/2026, 7:25 PMquaint-kitchen-99447
03/25/2026, 7:26 PMtall-airline-16756
03/25/2026, 7:27 PMturns: URL and your TLS certificate on the TURN host matches the NLB hostname clients use.
4) TLS certificate and SNI
• If the NLB is passthrough, TLS is terminated at the TURN instance — the TURN server must present a certificate valid for the public hostname.
• If the NLB does TLS termination (not typical for TURN), the cert must be on the NLB and the connection between NLB and TURN must be trusted (and LiveKit may need to be configured accordingly). Prefer passthrough to keep TURN TLS on the TURN instance.
5) Open required firewall/SG/host ports (UDP + TCP)
• At minimum ensure:
◦ TCP 443 (TURN over TLS) allowed from the internet to the NLB and to the TURN host.
◦ UDP 3478 (STUN/TURN) and UDP ephemeral ranges (commonly 50000–60000) allowed if you use UDP relays.
◦ Any ports LiveKit requires for SFU media (e.g., UDP media ports) open between LB and host.
• The LiveKit tester output explicitly warned about blocked ports — double-check security groups, instance firewalls (ufw/iptables), and any corporate network firewalls.
6) coturn configuration highlights
• If using coturn, confirm:
◦ listening-port and tls-listening-port are set correctly for the ports you expose.
◦ external-ip is set if coturn is behind NAT.
◦ lt-cred-mech enabled and credentials or shared-secret match what LiveKit will use to generate credentials (or you advertise static user:pass).
◦ TLS cert and key paths are correct and readable by coturn.
7) LiveKit configuration
• In livekit.yaml, enable TURN and list the exact TURN URLs you expect clients to use. Example:
◦ urls:
▪︎ "turnsturn.example.com443?transport=tcp"
◦ secret: turn-shared-secret
• Restart LiveKit after changes.
8) Force relay mode to verify TURN
• On a test client, set iceTransportPolicy: 'relay' so the client uses TURN only. If that fails, TURN is unreachable or misconfigured.
Questions to narrow troubleshooting 1) Which TURN server software are you running (coturn or other)? Is TLS terminated on the NLB or on the TURN host? 2) What TURN URLs are configured in LiveKit (livekit.yaml) and what hostname do clients use to reach TURN? 3) Are you exposing UDP-based TURN (3478/relayed ports) through the NLB, or only TCP/TLS on 443? 4) Can you share the specific NLB listener & target group settings (protocol: TCP/UDP, health check type)? 5) Can you run a client with iceTransportPolicy: 'relay' and paste any new tester errors (or a short excerpt)?
If you prefer, tell me the answers to questions 1–3 and I’ll give the exact coturn settings, NLB listener example, and the precise livekit.yaml snippet you should use next.
, with interactive elementsquaint-kitchen-99447
03/25/2026, 7:33 PMtall-airline-16756
03/25/2026, 7:34 PMlistening-port=3478 and/or tls-listening-port=5349 or 443 if you configured TLS there.
◦ If coturn sits behind NAT, set external-ip=<public-ip> so allocations return correct addresses.
◦ TLS cert/key paths must be correct and readable, and the cert must match the public hostname sent by clients.
◦ lt-cred-mech must be enabled and credentials or shared-secret must align with LiveKit config.
1. Firewall / security group checks (very common cause)
◦ Ensure inbound from internet → NLB: TCP 443 (and UDP ports if used).
◦ Ensure NLB → TURN host: same ports allowed.
◦ Ensure LiveKit server and TURN host can reach each other as needed (if LiveKit generates TURN credentials or talks to TURN).
◦ If you rely on UDP relays, allow ephemeral RTP ranges (commonly 50k‑60k UDP) to the TURN host.
1. Force relay (diagnostic)
◦ On a test client set iceTransportPolicy: 'relay' to force using TURN only. If this fails, TURN is not reachable or credentials/certs are wrong.
◦ Watch the browser console and the LiveKit tester for TURN allocation errors or authentication failures.
1. Inspect logs for TURN allocation/auth errors
◦ coturn logs will show allocations and auth attempts. If you see failed auth or no incoming allocation attempts, the client isn’t reaching coturn.
◦ LiveKit logs should show which ICE servers are supplied to the client and any TURN credential generation errors.
Targeted things I noticed in your logs you should confirm
• The ICE candidate shown is a private host candidate (172.16.x.x). No server reflexive or relay candidate is shown — that indicates the client didn’t receive STUN/TURN reflexive or TURN relay candidates.
• Signaling (WebSocket) is working, so token and signalling paths are fine; the break is in gathering usable remote candidates.
Quick clarifying questions so I can give exact config snippets
1. Which TURN software are you running (coturn)? Is TLS terminated at the NLB or on the TURN instance (passthrough)?
2. What TURN URLs are currently configured in livekit.yaml (paste the urls: lines, redact secrets)?
3. Are you exposing UDP 3478 (or other UDP ports) through the NLB, or only TCP/TLS 443?
4. Can you share a short excerpt of coturn logs when a client attempts to connect (auth success/failure or allocation lines)?
If you prefer, answer 1–3 and I’ll provide:
• Exact coturn config for passthrough on port 443 (with external-ip, TLS config, and recommended options)
• Example NLB listener/target group settings for TCP passthrough and optional UDP listeners
• The precise livekit.yaml snippet you should use (TURN URLs + secret) and the test steps to validate success
I’ll wait for your answers and can walk you through the exact coturn and LiveKit config to get relay candidates to appear in ICE.
Sources: Agents telephony integration | LiveKit Documentation | Running LiveKit on AWS | LiveKit | Zscaler proxy configuration | Firewall Tips | Diagnosing Connection Errors with Connection Test Utility, with interactive elementsquaint-kitchen-99447
03/25/2026, 7:39 PMtall-airline-16756
03/25/2026, 7:43 PMport: 7880
bind_addresses: [""]
rtc:
tcp_port: 7881
port_range_start: 50000
port_range_end: 60000
keys:
your_api_key: your_api_secret
logging:
level: info
• Expose health check endpoint (default: :8081/health) and use it for LB health checks.
3) Deploy and configure TURN servers (coturn)
• Use coturn as a production TURN implementation.
• Run coturn on machines with public IPs or behind NLB passthrough.
• Example /etc/turnserver.conf highlights:
◦ listening-port=3478
◦ tls-listening-port=5349 (or 443 if you want TLS on 443)
◦ external-ip=PUBLIC_IP or public_ip/PRIVATE_IP (if behind NAT)
◦ realm=turn.example.com
◦ lt-cred-mech
◦ fingerprint
◦ cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
◦ pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem
◦ min-port / max-port for relay range (e.g., 50000–60000)
• Ensure coturn runs as a service and logs show successful allocation when clients connect.
4) Load balancer topology & configuration
• Signaling (WSS/HTTPS):
◦ ALB or reverse proxy (nginx) terminates TLS → forward to LiveKit port 7880.
◦ ALB target group use HTTP or TCP as appropriate; health check on 8081/health.
• TURN:
◦ Use NLB in passthrough mode for TURN so coturn presents TLS certificate and supports UDP.
◦ NLB listeners:
▪︎ TCP 443 → targets TCP 443 (coturn TLS)
▪︎ UDP 3478 → targets UDP 3478 (coturn STUN/TURN UDP) if used
▪︎ UDP relay range as needed (or ensure coturn relays on dynamic ports and those are reachable)
◦ Target health checks should be TCP or TLS where passthrough is used.
• If you cannot expose UDP through NLB (cloud restriction), ensure TURN over TCP/TLS on 443 is available and advertise turns: URLs.
5) Firewall & Security groups (most critical)
• From internet → ALB/NLB:
◦ TCP 443 (WSS/HTTPS and TURN/TLS)
◦ UDP 3478 (STUN/TURN) if using UDP
◦ UDP 50000–60000 (relay RTP/RTCP) if you expose relay UDP ports
• ALB/NLB → instance security groups/hosts: same ports allowed.
• LiveKit internal ports:
◦ TCP 7880 (signaling)
◦ TCP 7881 (rtc/tcp)
◦ UDP 50000–60000 (media)
• For corporate clients: ensure your organization’s firewall allows outbound TCP 443. UDP may be blocked — that’s why TURN over TLS (443) is the most reliable fallback.
• If corporate network uses DPI (e.g., Zscaler), add bypass rules for your TURN and LiveKit domains, or work with security team to allow the traffic.
6) Configure LiveKit to advertise TURN servers
• In livekit.yaml or via env, add ICE servers:
rtc:
ice_servers:
- urls:
- "turn:turn.example.com:3478?transport=udp"
- "turn:turn.example.com:3478?transport=tcp"
- "turns:turn.example.com:443?transport=tcp"
username: "username" # OR use shared-secret approach
credential: "password"
• Alternatively configure LiveKit’s turn.secret to generate ephemeral credentials (preferred) and ensure coturn is configured to accept the same credential mechanism (long‑term or ephemeral).
7) Security and secrets
• Use long‑term credential mechanism (lt-cred-mech) or short lived (credential generation using a shared secret).
• Store API keys and secrets in a secrets store (AWS Secrets Manager, Vault) — not in plain repo.
• Enforce TLS 1.2/1.3; disable older cipher suites.
8) Test connectivity step by step
• From public client network:
a. WebSocket: verify wss://livekit.example.com connects.
• curl -vk https//livekit.example.com443/ (returns or shows TLS handshake)
a. TURN reachability:
• openssl s_client -connect turn.example.com:443 -servername turn.example.com
• If passthrough: you should see coturn certificate presented.
a. Run LiveKit Connection Tester (or ConnectionCheck in client SDK):
• checkWebsocket(), checkWebRTC(), checkTURN()
a. Force TURN on a test client:
• set rtcConfig: { iceTransportPolicy: 'relay' } and try to publish audio/video. This ensures you test relay path only.
a. Use browser devtools to inspect ICE candidates: look for server reflexive (srflx) or relay candidates. If only host candidates appear, TURN never reached the client.
9) Troubleshooting checklist (if ICE never shows relay candidates)
• Ensure TURN URLs sent to clients match the public hostname and transport (turns: for TLS).
• Verify coturn logs for incoming allocate/auth requests — if none, the client isn’t reaching the TURN server (LB/firewall issue).
• Check NLB listener/protocol: NLB must forward TCP/UDP (not terminate TLS) for coturn passthrough.
• Confirm TLS certificate SNI matches hostname clients use. Mismatched cert triggers connection failure.
• Confirm security groups/iptables allow NLB → coturn → port ranges.
• If behind corporate DPI/proxy, ask IT to whitelist domains or use TLS on 443 and ensure SNI is allowed.
10) Production hardening & HA
• Run multiple LiveKit nodes across AZs; use DNS or geo LB to direct clients to nearest region.
• Run multiple coturn nodes behind NLB; advertise multiple TURN URLs in LiveKit so clients can failover.
• Autoscale LiveKit workers and coturn based on load; set graceful drain times for audio sessions (10+ minutes).
• Monitor: CPU, memory, number of active peers, ICE failures, TURN allocations. Set alerts on high ICE failure rate.
11) Monitoring and logs
• Collect LiveKit logs (info/debug when troubleshooting), coturn logs, and LB/NGINX logs centrally (ELK/CloudWatch).
• Alert on:
◦ rising percentage of ICE failures
◦ TURN allocation errors and authentication failures
◦ high packet loss or CPU spikes
Quick commands & snippets
• Start coturn (Ubuntu):
sudo apt-get install coturn
edit /etc/turnserver.conf as described, then
sudo systemctl enable coturn sudo systemctl start coturn
• Test TLS to TURN:
openssl s_client -connect turn.example.com:443 -servername turn.example.com
• Force TURN in JS client:
await room
Sources: Running LiveKit on AWS | LiveKit | Self-hosted deployments | LiveKit Documentation | Firewall Tips | Zscaler proxy configuration | Security Overview | LiveKit, with interactive elementsquaint-kitchen-99447
04/16/2026, 1:24 PMtall-airline-16756
04/16/2026, 1:24 PMquaint-kitchen-99447
04/30/2026, 9:07 AMtall-airline-16756
04/30/2026, 9:08 AMquaint-kitchen-99447
04/30/2026, 9:08 AMtall-airline-16756
04/30/2026, 9:09 AMquaint-kitchen-99447
04/30/2026, 9:09 AMtall-airline-16756
04/30/2026, 9:10 AMquaint-kitchen-99447
04/30/2026, 9:14 AMtall-airline-16756
04/30/2026, 9:14 AMiceTransportPolicy: 'relay')., with interactive elements