That 50000-50100 range creates 101 individual iptables/nftables rules in the Docker proxy. On my system this caused the entire Docker networking stack to hang — all containers lost connectivity and the host became unresponsive. Had to hard reboot. This will hit anyone whose Docker setup uses iptables-based port mapping (the default).
Solution: host networking
LiveKit works much better with network_mode: host. It binds directly to the host's interfaces, avoids the port mapping overhead entirely, and also solves NAT hairpinning issues.
With Docker's bridge networking, WebRTC clients on the same LAN as the server couldn't connect — the ICE candidates advertised the external IP, but hairpin NAT back through the router failed. Host networking eliminates this since LiveKit sees the real network interfaces and can advertise both internal and external IPs correctly.
In the LiveKit config, restrict which interfaces/subnets it listens on so it picks up the right IP:
rtc:tcp_port:7881udp_port:7882use_external_ip:truenode_ip:<your-public-ip>interfaces:includes:-br0# your LAN-facing interfaceips:includes:-192.168.0.0/24# your LAN subnetturn:enabled:trueudp_port:3479# remapped from 3478 to avoid conflicts (e.g. Nextcloud Talk)
Since it's on the host network, the LiveKit signaling endpoint needs to go through Traefik using the host IP rather than the Docker service name. The wss:// signaling URL in Fluxer config points to a Traefik route that proxies to 127.0.0.1:7880.
Dynamic IP and the node_ip problem
node_ip in the LiveKit config tells clients which IP to send media to. If you're on a residential connection with a dynamic IP, this value goes stale when your IP changes. LiveKit reads the config once at startup and has no mechanism to detect IP changes.
My workaround uses three scripts:
Entrypoint — resolves a DDNS hostname to an IP at startup:
Autoheal — a container like willfarrell/autoheal watches for unhealthy containers and restarts them. When the healthcheck fails due to IP change, autoheal restarts LiveKit, which re-runs the entrypoint and picks up the new IP.
This is a hack — there's a window between IP change and restart where voice is broken. A proper fix would be LiveKit supporting periodic IP re-resolution or a reload signal, but this works well enough for a home setup where IP changes are infrequent.
Port forwarding summary
With host networking, forward these on your router to the Fluxer host:
Port
Protocol
Purpose
3479
UDP
TURN/STUN
7881
TCP
ICE TCP fallback
7882
UDP
Primary media (RTP/RTCP)
Note: the upstream default uses 50000-50100/udp as the RTP range. With a single udp_port instead, LiveKit multiplexes all media over one port. This is fine for a small instance and avoids the port range mapping issue entirely.
Thread
Comment by @mgabor3141
7: LiveKit deployment — port mapping crash, host networking, and dynamic IP
Docker port mapping crash with UDP ranges
The upstreamcompose.yamlmaps LiveKit ports like this:50000-50100range creates 101 individual iptables/nftables rules in the Docker proxy. On my system this caused the entire Docker networking stack to hang — all containers lost connectivity and the host became unresponsive. Had to hard reboot. This will hit anyone whose Docker setup uses iptables-based port mapping (the default).Solution: host networking
LiveKit works much better withnetwork_mode: host. It binds directly to the host's interfaces, avoids the port mapping overhead entirely, and also solves NAT hairpinning issues. With Docker's bridge networking, WebRTC clients on the same LAN as the server couldn't connect — the ICE candidates advertised the external IP, but hairpin NAT back through the router failed. Host networking eliminates this since LiveKit sees the real network interfaces and can advertise both internal and external IPs correctly.wss://signaling URL in Fluxer config points to a Traefik route that proxies to127.0.0.1:7880.Dynamic IP and the
node_ipproblemnode_ipin the LiveKit config tells clients which IP to send media to. If you're on a residential connection with a dynamic IP, this value goes stale when your IP changes. LiveKit reads the config once at startup and has no mechanism to detect IP changes. My workaround uses three scripts: Entrypoint — resolves a DDNS hostname to an IP at startup:willfarrell/autohealwatches for unhealthy containers and restarts them. When the healthcheck fails due to IP change, autoheal restarts LiveKit, which re-runs the entrypoint and picks up the new IP.Port forwarding summary
With host networking, forward these on your router to the Fluxer host:50000-50100/udpas the RTP range. With a singleudp_portinstead, LiveKit multiplexes all media over one port. This is fine for a small instance and avoids the port range mapping issue entirely.