white-oxygen-36812
02/25/2026, 1:28 PM# Ingress
apiVersion: <http://networking.k8s.io/v1|networking.k8s.io/v1>
kind: Ingress
metadata:
name: livekit-mediaserver
annotations:
<http://cert-manager.io/cluster-issuer|cert-manager.io/cluster-issuer>: "cloudflare-issuer-for-livekit"
<http://nginx.ingress.kubernetes.io/enable-cors|nginx.ingress.kubernetes.io/enable-cors>: "true"
<http://nginx.ingress.kubernetes.io/cors-allow-origin|nginx.ingress.kubernetes.io/cors-allow-origin>: "*"
<http://nginx.ingress.kubernetes.io/ssl-redirect|nginx.ingress.kubernetes.io/ssl-redirect>: "true"
<http://nginx.ingress.kubernetes.io/proxy-read-timeout|nginx.ingress.kubernetes.io/proxy-read-timeout>: "3600"
<http://nginx.ingress.kubernetes.io/proxy-send-timeout|nginx.ingress.kubernetes.io/proxy-send-timeout>: "3600"
<http://nginx.ingress.kubernetes.io/proxy-connect-timeout|nginx.ingress.kubernetes.io/proxy-connect-timeout>: "3600"
<http://nginx.ingress.kubernetes.io/proxy-buffering|nginx.ingress.kubernetes.io/proxy-buffering>: "off"
spec:
ingressClassName: nginx
tls:
- hosts:
- <http://website.com|website.com>
secretName: livekit-tls
rules:
- host: <http://website.com|website.com>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: livekit-server
port:
number: 443
In Digitalocean dashboard we have:
• backend keepalive: disabled
• http idle timeout 60
• proxy protocol: disabled
Are we missing something?
Wondering because we have edge cases with this errors:
• Could not connect to room: could not establish signal connection: Failed to fetch
• Could not connect to room: could not establish signal connection: Encountered websocket error during connection establishment
• provider: connection aborted
• Could not connect to room: could not establish pc connectiontall-airline-16756
02/25/2026, 1:29 PMtall-airline-16756
02/25/2026, 1:29 PMproxy-read-timeout, proxy-send-timeout, and proxy-connect-timeout set high (you already have 3600s).
◦ Ensure proxy buffering is off (you already set proxy-buffering: "off").
1. Enable keepalives where appropriate
◦ If DigitalOcean LB supports backend keepalive, try enabling it to reduce connection churn. If enabling causes issues, try toggling it back — observe behavior.
1. Proxy protocol / TLS passthrough
◦ If you need original client IPs, enable proxy protocol where supported and ensure your backend supports it.
◦ If the LB terminates TLS (Application LB), make sure WebSocket TLS upgrade flows correctly to backend. Consider passthrough (Network LB) and terminate TLS at LiveKit if simpler.
1. TURN fallback
◦ Make sure you have a reachable TURN server (TURN over TCP/TLS) for clients behind restrictive networks. TURN over TCP/443 can help when UDP is blocked.
◦ Confirm LiveKit is configured with the TURN credentials and reachable host/ports.
1. Test connectivity with connection-check utilities
◦ Run WebSocket and UDP connectivity tests from the client network to the LB public IP to confirm:
▪︎ WebSocket (wss://) connects and remains open beyond 60s.
▪︎ UDP to port 7882 reaches the backend (or TURN) and STUN works.
Optional Kubernetes considerations
• If you switch to a Network LB that forwards UDP/TCP to nodes, the Ingress may become redundant for signaling. You can:
◦ Use the LB to forward 443 directly to the node/LiveKit Service NodePort for signaling and UDP directly to the node.
◦ Or use a Service of type LoadBalancer that supports both TCP and UDP (if DO supports that) and expose the correct ports.
Quick checklist you can run now
• [ ] Is your DO load balancer a Network/pass-through LB? If not, consider switching.
• [ ] Is UDP 7882 open and forwarded through the LB and node firewall?
• [ ] Increase DO LB idle timeout (if you’re relying on Application LB signaling) to match ingress timeouts.
• [ ] Ensure TURN is configured and reachable (TURN over TCP/443 as fallback).
• [ ] Confirm NGINX ingress timeouts are actually in effect (no LB override).
If you want, I can help further if you share:
• Which type of DigitalOcean load balancer you’re using (Application vs Network).
• Whether you have TURN configured and its ports/protocols.
• How LiveKit is exposed in Kubernetes (Service type: ClusterIP/NodePort/LoadBalancer) and whether you’re using hostNetwork or a NodePort for UDP.
I can then give step-by-step changes tailored to your cluster and DO LB type.
Sources: Firewall Tips for LiveKit Connectivity | LiveKit | Diagnosing Connection Errors with Connection Test Utility | Running LiveKit on AWS | Running LiveKit on AWSwhite-oxygen-36812
02/25/2026, 1:34 PMtall-airline-16756
02/25/2026, 1:34 PMwhite-oxygen-36812
02/25/2026, 1:36 PM# Ingress
apiVersion: <http://networking.k8s.io/v1|networking.k8s.io/v1>
kind: Ingress
metadata:
name: livekit-mediaserver
annotations:
<http://cert-manager.io/cluster-issuer|cert-manager.io/cluster-issuer>: "cloudflare-issuer-for-livekit"
<http://nginx.ingress.kubernetes.io/enable-cors|nginx.ingress.kubernetes.io/enable-cors>: "true"
<http://nginx.ingress.kubernetes.io/cors-allow-origin|nginx.ingress.kubernetes.io/cors-allow-origin>: "*"
<http://nginx.ingress.kubernetes.io/ssl-redirect|nginx.ingress.kubernetes.io/ssl-redirect>: "true"
<http://nginx.ingress.kubernetes.io/proxy-read-timeout|nginx.ingress.kubernetes.io/proxy-read-timeout>: "3600"
<http://nginx.ingress.kubernetes.io/proxy-send-timeout|nginx.ingress.kubernetes.io/proxy-send-timeout>: "3600"
<http://nginx.ingress.kubernetes.io/proxy-connect-timeout|nginx.ingress.kubernetes.io/proxy-connect-timeout>: "3600"
<http://nginx.ingress.kubernetes.io/proxy-buffering|nginx.ingress.kubernetes.io/proxy-buffering>: "off"
spec:
ingressClassName: nginx
tls:
- hosts:
- <http://website.com|website.com>
secretName: livekit-tls
rules:
- host: <http://website.com|website.com>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: livekit-server
port:
number: 443tall-airline-16756
02/25/2026, 1:36 PMwhite-oxygen-36812
02/25/2026, 1:37 PMtall-airline-16756
02/25/2026, 1:37 PM<http://service.beta.kubernetes.io/do-loadbalancer-type|service.beta.kubernetes.io/do-loadbalancer-type>: "REGIONAL_NETWORK", whether it makes sense for LiveKit, and any downsides.
What this annotation does
• Setting <http://service.beta.kubernetes.io/do-loadbalancer-type|service.beta.kubernetes.io/do-loadbalancer-type>: "REGIONAL_NETWORK" tells DigitalOcean to provision a Network (pass-through) Load Balancer for that Kubernetes Service instead of an Application/HTTP(S) Load Balancer.
• A Network LB forwards TCP and UDP traffic at layer 4 without terminating TLS or doing HTTP host/path routing.
Why this makes sense for LiveKit
• LiveKit requires UDP for media (commonly UDP 7882) in addition to TCP/HTTPS (signaling). A Network LB can forward UDP to your nodes, which an Application LB cannot.
• Using a Network LB removes the Application LB’s HTTP idle timeout and TLS termination behavior that was causing WebSocket timeouts and blocked UDP media in your previous setup.
• Overall, this annotation aligns the infrastructure with LiveKit’s requirements: signaling over TCP/443 and media over UDP.
Potential downsides / considerations
• TLS termination moves to your backend:
◦ The Network LB typically passes TLS through. You must terminate TLS on your ingress controller (NGINX) or directly in the LiveKit pods and manage certificates there (cert-manager + ingress is a common choice).
• No L7 routing at the LB:
◦ Host/path routing and automatic certificate provisioning that an Application LB provides will not be handled at the LB layer. Keep your Ingress and cert-manager to continue hostname routing and certificate management.
• Health checks and session handling:
◦ Choose appropriate health checks (TCP or custom) so the LB doesn’t mark nodes unhealthy. The checks are simpler at L4 versus L7, so plan accordingly.
• NodePort / port exposure:
◦ The DO Network LB will forward to node IPs and node ports. You may need to expose the LiveKit ports (TCP 443 and UDP 7882) via a Service of type NodePort or use hostNetwork. Confirm your Service manifest.
• Costs and regional behavior:
◦ Network Load Balancers may have different pricing or regional scope. Using REGIONAL_NETWORK ensures regional availability but check DO billing/limits if cost is a concern.
• Client IPs and proxy protocol:
◦ If you need original client IPs preserved, configure proxy protocol support and ensure your backend supports it. Without it, the backend will see the node/LB IPs.
Short practical checklist to apply safely
1. Confirm your LiveKit Service exposes TCP 443 and UDP 7882 (NodePort or hostNetwork).
2. Add the annotation to the Service and apply it. This should create a Network LB that forwards both TCP and UDP.
3. Ensure certs and TLS are configured on the backend (NGINX or LiveKit), since LB won’t terminate TLS.
4. Open node/Droplet firewalls for TCP 443 and UDP 7882.
5. Configure health checks (TCP) that match a healthy LiveKit endpoint.
6. Test: verify stable wss:// signaling and successful ICE/media (no more “pc connection” errors).
7. Confirm TURN is configured as fallback for restrictive clients.
If you’d like, paste the current Service manifest for livekit-server (type, ports, any existing annotations). I’ll review it and provide exact manifest changes and the safe sequence to migrate to REGIONAL_NETWORK without downtime.