How to deploy TURN servercoturn inside Kubernetes
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Running Coturn in Kubernetes is possible, but TURN servers are more network-sensitive than ordinary HTTP services. The hard part is not the container image. The hard part is exposing the right external IP and relay port range so clients can actually negotiate media through the server.
Understand the Network Requirements First
A TURN server normally needs:
- the listener port, commonly
3478for UDP and TCP - optional TLS port, often
5349 - a relay port range for media traffic
- a stable public IP that clients can reach
This is where Kubernetes complicates things. TURN relay traffic is not confined to one small service port. Coturn allocates relay ports dynamically, so if you keep the default huge port range, the Kubernetes service definition becomes awkward very quickly.
That is why most real deployments do one of two things:
- restrict Coturn to a smaller relay port range
- use
hostNetworkor another direct-networking approach
A Minimal Coturn Configuration
A practical turnserver.conf for Kubernetes usually includes a narrowed relay range and explicit external identity:
The external-ip value matters because WebRTC clients need the correct public address in the ICE candidates. If Coturn advertises the wrong IP, connectivity fails even though the pod is running.
Deploy the Pod and Expose the Ports
A simplified deployment might look like this:
And the service:
This is only the control path. If you restrict the relay range, you also need that range routable through your environment. That is the part many first deployments miss.
Why hostNetwork Is Often Considered
TURN is sometimes easier on hostNetwork because the pod can bind directly to the node’s network stack, which avoids extra address translation confusion and makes relay port handling more straightforward.
That is not mandatory, but it is a legitimate choice when:
- you need predictable public IP behavior
- UDP relay ports must map cleanly
- your load balancer setup is limited
Kubernetes is not fighting you here. TURN simply has different networking assumptions than a typical REST API.
Authentication and Secrets
Do not bake shared secrets directly into the image. Store them in a Kubernetes Secret and mount or inject them into the Coturn config.
For WebRTC deployments, long-term credentials with use-auth-secret are a common pattern because the application can mint short-lived TURN credentials instead of storing a permanent username and password in clients.
Common Pitfalls
The biggest mistake is exposing only port 3478 and forgetting that TURN also needs a relay port range for media traffic.
Another issue is advertising the wrong external IP. Coturn may be healthy, logs may look fine, and the service may still fail because the ICE candidates contain an unreachable address.
Developers also often treat TURN like a normal web service and hide it behind networking layers that do not handle UDP relay traffic well. TURN is far more sensitive to NAT and port mapping details.
Finally, avoid leaving the relay range wide open by default in Kubernetes. Narrow it deliberately so you can reason about firewall rules, service exposure, and observability.
Summary
- Coturn in Kubernetes is mainly a networking problem, not a container problem.
- Restrict the relay port range and make sure it is actually reachable.
- Configure the correct external IP so clients get valid ICE candidates.
- Consider
hostNetworkif service-based exposure makes relay traffic too awkward. - Store TURN secrets in Kubernetes secrets and test with real WebRTC clients, not just pod health checks.

