Urgent.News

What's breaking now, across thousands of outlets.

Tech

What breaks when you self-host a TURN server (coturn — symptom, cause, fix)

The first article in this series was the traps inside the code. The second was the layer underneath — the candidates that lie, the UDP firewall nobody looks at, the reverse proxy that reaps an idle socket. This one is about the piece people reach for when those two are not enough: the relay. TURN is the part of WebRTC that gets configured last, in a hurry, by copying a config off a blog post.…

When self-hosting a TURN server (coturn), there are several issues that can arise, causing failures in the relay service. These problems are often subtle and lack clear error messages, making them difficult to diagnose.

First, it is essential to determine whether TURN is even the right solution for your situation. Adding a relay to a system with an unrelated problem can mask the underlying issue, making debugging more challenging. To check this, look at the candidate type selected in chrome://webrtc-internals (or about:webrtc in Firefox). If the type is "relay," TURN is functioning correctly, and the issue lies elsewhere. If it is "srflx" or "host," TURN is not being used, and the problem is with the ICE configuration.

Second, ensure that the relay is properly configured and operational. A server advertising an unroutable address or a closed UDP media range can produce the same symptoms as a dead relay, such as signaling appearing green, ICE stuck in checking mode, and then failing. To rule these issues out, first verify that the coturn service is running correctly.

On Debian and Ubuntu, the package includes an /etc/default/coturn file that controls whether the service starts, typically using either an init script or a systemd unit file. If the service fails to start, but the package reports success, the issue lies within this file. Additionally, check that the ports (3478 and 5349) are bound by ensuring they appear in the output of `ss -lunp | grep -E "^3478|^5349"` and by reviewing the coturn service logs with `journalctl -u coturn -n 50 --no-pager`.

If the service is running and bound to the necessary ports, the relay address might be pointing inward instead of outward. This occurs when the machine's public IP address is not correctly advertised as the relay address. This problem is similar to the one observed in the previous article about reverse proxies. To fix this, configure the external IP address as the relay's public address, with the private address as the secondary address, separated by a slash.

It is also common to only set the public address, which can be a half-fix until the server needs to bind locally.

Lastly, ensure that the relay port range is correctly configured and open in both firewalls. The relay allocates a port to each client from a range of ports, typically 49152 to 65535. If the media does not flow, it could be due to a firewall blocking the relay port range. Open the relay port range in both the provider's security group and the host's own firewall rules (such as ufw or iptables).

On most cloud providers, the security group is the primary firewall rule, while the host firewall is less relevant. However, on a VPS with an extensive iptables ruleset, the opposite may be true. Open UDP ports only, as browsers will use UDP for TURN whenever it is available. Opening only TCP will not work, as TURN relies on UDP for media transmission.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Never silently change a number someone gets paid on

Our algorithm decided a driver had travelled 4km less than they thought. It was probably right. Shipping that silently would still have been wrong.

  • Algorithm may adjust mileage recorded by drivers
  • Transparency required: show original vs. adjusted distance
  • Drivers should override algorithm decisions if needed

React.js ~The Latest Ref Pattern ~

This pattern holds callback passed to a customhook in the ref and update existing value everytime rendered to have the latest value.

  • Ref maintains a current value without triggering re-render, preventing infinite loops.
  • React 19 introduces useEffectEvent to incorporate the latest Ref pattern into the official API.

More from Sunday 20 September →