From 0dada0e3db13404e719cc3140cbce81f48aad69a Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Fri, 12 Jun 2026 19:07:41 +0000 Subject: [PATCH 1/2] fix(sfu): only advertise the primary public IP in ICE candidates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LiveKit was offering host candidates for every local mapping: the real public IP, the DO reserved IP (NAT'd via the anchor IP 10.48.x), the VPC IP, and the docker bridge. ICE flapped between the real-IP and reserved-IP pairs (10 switches in 30 min in prod logs), and the reserved IP's NAT drops UDP mid-session — publishers died with dtls timeouts and clients surfaced "could not establish pc connection" a minute or two into streaming. Pin candidate gathering to ${EXTERNAL_IP} via rtc.ips.includes. Co-Authored-By: Claude Fable 5 --- apps/livekit/setup-livekit-server.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/livekit/setup-livekit-server.sh b/apps/livekit/setup-livekit-server.sh index 754d53a..1f55096 100755 --- a/apps/livekit/setup-livekit-server.sh +++ b/apps/livekit/setup-livekit-server.sh @@ -333,6 +333,14 @@ rtc: udp_port: 7882 use_external_ip: true node_ip: ${EXTERNAL_IP} + # Only advertise the primary public IP. Without this, LiveKit also offers + # candidates for the DO reserved IP (NAT'd through the droplet's anchor IP), + # the VPC IP, and the docker bridge. ICE flaps between the real IP and the + # reserved-IP path, whose NAT drops UDP mid-session — clients die with + # "could not establish pc connection" a minute or two into a stream. + ips: + includes: + - ${EXTERNAL_IP} keys: ${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET} From 0a327137cb5c00ec48bd7ca29c796407090916e1 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Fri, 12 Jun 2026 19:15:33 +0000 Subject: [PATCH 2/2] fix(sfu): ips.includes requires CIDR notation (/32) livekit-server rejects bare IPs in rtc.ips.includes with 'invalid CIDR address' and crash-loops. Verified on sfu.pairux.com: with /32 the server starts and advertises only the primary IP. Co-Authored-By: Claude Fable 5 --- apps/livekit/setup-livekit-server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/livekit/setup-livekit-server.sh b/apps/livekit/setup-livekit-server.sh index 1f55096..649f64d 100755 --- a/apps/livekit/setup-livekit-server.sh +++ b/apps/livekit/setup-livekit-server.sh @@ -340,7 +340,7 @@ rtc: # "could not establish pc connection" a minute or two into a stream. ips: includes: - - ${EXTERNAL_IP} + - ${EXTERNAL_IP}/32 keys: ${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET}