Troubleshooting WebRTC connection failures with Caddy reverse proxy

This question originally came up in our Slack community and the thread has been consolidated here for long-term reference.

I’m self-hosting LiveKit on Ubuntu VM behind Caddy reverse proxy. The LiveKit server and token generator are working, but my frontend can’t connect.

Browser shows:

  • WebSocket to wss://domain.com/rtc opens then closes instantly
  • GET /rtc/rtc/validate returns 404
  • ICE connection state goes from new → closed immediately

LiveKit logs show it fails to detect external IP. Should I set rtc.use_external_ip: true and external_ip in livekit.yaml?

There were a couple of root causes found here:

1. Duplicate /rtc in URL: The URL was wss://domain.com/rtc/rtc - the /rtc gets appended automatically, so remove it from your base URL configuration.

2. External IP detection: The server couldn’t discover or advertise its external IP properly, causing ICE/DTLS handshake failures.

Debugging tips:

  • Use chrome://webrtc-internals/ in one tab while connecting in another - this gives you all WebRTC debug info in real-time
  • Check what ICE candidates are being advertised
  • Verify your websocket URL is correct and DNS is resolving properly

Common causes of ICE failures:

  • VPN interference - disable VPN for testing
  • Missing or incorrect external_ip configuration
  • TURN not configured when needed

For production environments, discuss TURN/STUN configuration options to ensure reliable connectivity.