fix(server): emit correct CIDR prefix in rtc.ips.includes (IPv4 /32, IPv6 /128) #37

Merged
sameh-farouk merged 1 commit from fix/render-livekit-yaml-ipv4-cidr into main 2026-04-30 12:43:05 +00:00
Member

Closes #36.

Summary

render_livekit_yaml hardcoded /128 in the rtc.ips.includes line, which is the right prefix for IPv6 single-host (mycelium multi-user deploys) but invalid CIDR for IPv4 — Pion rejects the config and livekit-server crashes on startup with invalid CIDR address: <IPV4>/128.

Detect the address family via IpAddr::parse():

  • IPv4 literal → /32
  • IPv6 literal → /128 (unchanged)
  • Hostname / non-literal → skip the include block entirely (Pion's CIDR parser rejects non-literal anyway, and binding on all global IPs is the safe default on single-user hosts where there's no sibling-user collision to worry about)

Test plan

  • Single-user IPv4 (TF Grid VM, public 185.206.122.48): before patch — invalid CIDR crash; after patch — yaml renders 185.206.122.48/32, livekit-server binds UDP :7882 + TCP :7881 + TCP :7880 cleanly, signaling reachable through nginx, browser huddle works end-to-end.
  • Multi-user mycelium (sameh's slot on shared host, IPv6 4a0:6976:8fa7:efc:5::1): yaml renders 4a0:6976:8fa7:efc:5::1/128 — identical to pre-patch behavior. No regression. livekit-server bound on the per-user ports.
  • cargo build -p hero_livekit_server clean (no new warnings)

Compatibility

  • Multi-user mycelium deploys: zero behavioral change.
  • Single-user IPv4 deploys: were broken; now work.
  • Hostname-based deploys: previously emitted /128 after a hostname (also invalid); now skip the block. This is a behavioral change but the previous behavior was already broken.
Closes #36. ## Summary `render_livekit_yaml` hardcoded `/128` in the `rtc.ips.includes` line, which is the right prefix for IPv6 single-host (mycelium multi-user deploys) but invalid CIDR for IPv4 — Pion rejects the config and livekit-server crashes on startup with `invalid CIDR address: <IPV4>/128`. Detect the address family via `IpAddr::parse()`: - IPv4 literal → `/32` - IPv6 literal → `/128` (unchanged) - Hostname / non-literal → skip the include block entirely (Pion's CIDR parser rejects non-literal anyway, and binding on all global IPs is the safe default on single-user hosts where there's no sibling-user collision to worry about) ## Test plan - [x] **Single-user IPv4 (TF Grid VM, public 185.206.122.48):** before patch — `invalid CIDR` crash; after patch — yaml renders `185.206.122.48/32`, livekit-server binds UDP :7882 + TCP :7881 + TCP :7880 cleanly, signaling reachable through nginx, browser huddle works end-to-end. - [x] **Multi-user mycelium (sameh's slot on shared host, IPv6 `4a0:6976:8fa7:efc:5::1`):** yaml renders `4a0:6976:8fa7:efc:5::1/128` — identical to pre-patch behavior. No regression. livekit-server bound on the per-user ports. - [x] `cargo build -p hero_livekit_server` clean (no new warnings) ## Compatibility - Multi-user mycelium deploys: zero behavioral change. - Single-user IPv4 deploys: were broken; now work. - Hostname-based deploys: previously emitted `/128` after a hostname (also invalid); now skip the block. This is a behavioral change but the previous behavior was already broken.
fix(server): emit correct CIDR prefix in rtc.ips.includes (IPv4 /32, IPv6 /128)
Some checks failed
Build & Test / check (pull_request) Failing after 4s
9a3a6eda88
`render_livekit_yaml` hardcoded `/128` in the `rtc.ips.includes` line,
which is the right prefix for IPv6 single-host (mycelium multi-user
deploys) but invalid CIDR for IPv4 — Pion (livekit-server's UDP layer)
rejects the config and the daemon crashes on startup with:

    invalid CIDR address: <IPV4>/128

Reproduced on a single-user TF Grid VM where node_ip is a public IPv4
(e.g. `185.206.122.48`). The supervisor wrote the config but
livekit-server failed to bind RTC ports — no signaling, no media.

Detect the address family at config-render time:
- IPv4 literal → emit `/32`
- IPv6 literal → emit `/128` (unchanged for the multi-user path)
- Hostname / non-literal → skip the include block entirely. Pion's
  CIDR parser rejects anything that isn't an IP literal, and binding
  on all global IPs is the safe default on single-user hosts where
  there's no sibling-user collision to worry about.

The multi-user mycelium path remains identical: node_ip there is
always an IPv6 literal, so /128 is still the prefix that gets emitted.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_livekit!37
No description provided.