diff --git a/DEPLOY.md b/DEPLOY.md index abf10bb..2d94c65 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -213,14 +213,21 @@ The app mints join tokens with the secret (server-side only); the same key/secre - **Websockets Support: ON**. Request an SSL cert (Let's Encrypt) + Force SSL. - NPM reaches `livekit:7880` by container name — both are on `nginx_proxy_manager_default`. -**4. Open the media ports on the VPS firewall** (these are host-published by the compose service, -bypassing NPM — WebRTC media can't traverse an L7 proxy): -```bash -ufw allow 50000:50100/udp # WebRTC media (must match livekit.yaml port range) -ufw allow 7881/tcp # WebRTC-over-TCP fallback for restrictive networks -``` -If the VPS is behind NAT and LiveKit can't auto-detect its public IP, set `rtc.node_ip` in -`livekit.yaml` to `118.95.33.89` and redeploy. +**4. Media ports — NAT port-forward (REQUIRED here).** This box sits **behind NAT**: its only +interface is a private `192.168.88.61`; the public `118.95.33.89` (DNS) is mapped by an upstream +gateway. WebRTC media can't traverse NPM (L7), so the gateway/router must forward the media ports +to the box. To keep the ask minimal, LiveKit is configured for **one** UDP port + one TCP fallback: + +Ask whoever controls the network/gateway to forward, from `118.95.33.89` → `192.168.88.61`: +| Port | Proto | Purpose | +|------|-------|---------| +| 50000 | UDP | WebRTC media (all participants mux over this one port) | +| 7881 | TCP | WebRTC-over-TCP fallback (restrictive client networks) | + +`livekit.yaml` already pins `rtc.node_ip: 118.95.33.89` (auto-detect would pick the wrong outbound +IP behind this NAT). The host's local `ufw` is inactive, so no host-firewall change is needed — the +only requirement is the upstream port-forward above. Until it exists, signaling connects but media +won't flow (participants see each other's tiles but no video/audio). **5. Deploy** (the livekit service is behind a `sfu` compose profile, so it stays dormant on a normal deploy — start it explicitly): diff --git a/docker-compose.yml b/docker-compose.yml index 92a70a2..1d81cd2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,8 +43,8 @@ services: volumes: - ./livekit.yaml:/etc/livekit.yaml:ro ports: - - "7881:7881" # WebRTC over TCP (fallback) - - "50000-50100:50000-50100/udp" # WebRTC media (UDP) — must match livekit.yaml port range + - "7881:7881" # WebRTC over TCP (fallback) + - "50000:50000/udp" # single WebRTC media UDP port (must match livekit.yaml rtc.udp_port) networks: - npm diff --git a/livekit.yaml b/livekit.yaml index ca9c9e2..d5028c8 100644 --- a/livekit.yaml +++ b/livekit.yaml @@ -7,10 +7,12 @@ port: 7880 # signaling (HTTP/WS) — NPM proxies wss://livekit.bizgaze.com -> here rtc: tcp_port: 7881 # WebRTC-over-TCP fallback (restrictive networks) - port_range_start: 50000 # WebRTC media (UDP) — keep in sync with the published range in compose - port_range_end: 50100 - use_external_ip: true # discover the public IP for ICE candidates (VPS). Or set node_ip below. - # node_ip: 118.95.33.89 # uncomment + set if use_external_ip can't detect the public IP + udp_port: 50000 # SINGLE UDP media port (all participants mux over it) — minimizes + # the NAT port-forward to one UDP + one TCP port. + # This box sits behind NAT (private 192.168.88.61 behind public 118.95.33.89). Auto-detection + # would find the wrong (outbound) IP, so pin the inbound public IP clients actually reach. + use_external_ip: false + node_ip: 118.95.33.89 # Embedded TURN over TLS on 443 helps clients on locked-down networks. Left off by default because # NPM already owns 443; enable via a dedicated hostname + NPM stream if you need it (see DEPLOY.md).