docs(livekit): bind lk-jwt-service to 127.0.0.1:8071, not all interfaces (#24) #31

Merged
jared merged 1 commits from fix/lk-jwt-loopback into main 2026-10-18 19:45:48 -04:00
Owner

Refs #24. This changes the documentation only. The live host still needs the change below, which is an owner action on LXC 151.

voice-limit-guard (:8070) is meant to be the only way to get a LiveKit token: it enforces room caps and audio-only publish limits. But the drop-in set LIVEKIT_JWT_BIND=:8071, which means all interfaces. Any LAN or VPN host, or a compromised container, could POST http://10.10.10.29:8071/sfu/get and get an unguarded token. The guard is fail-open by design, so :8071 is the only hard boundary.

This PR: the setup steps and port table now use LIVEKIT_JWT_BIND=127.0.0.1:8071. The guard already calls http://127.0.0.1:8071 (GUARD_UPSTREAM), so nothing else changes.

To apply on LXC 151:

printf '[Service]\nEnvironment=LIVEKIT_JWT_BIND=127.0.0.1:8071\n' > /etc/systemd/system/lk-jwt-service.service.d/override.conf
systemctl daemon-reload && systemctl restart lk-jwt-service
ss -ltnp | grep 8071          # expect 127.0.0.1:8071
# from another LAN host: nc -zv 10.10.10.29 8071 → refused; a call still connects via :8070

LIVEKIT_JWT_BIND is handed to Go's http.ListenAndServe upstream, so host:port works. I couldn't run the real binary locally (the dev stack uses a stand-in), so please check with ss after applying.

Not covered: the issue also flags LiveKit metrics 6789, Hookshot 9004, node_exporter 9100 and the matrix-admin exporter 9101 on 0.0.0.0. Restricting those depends on where Prometheus scrapes from, so I left them.

🤖 Generated with Claude Code

https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5

Refs #24. **This changes the documentation only. The live host still needs the change below, which is an owner action on LXC 151.** `voice-limit-guard` (`:8070`) is meant to be the only way to get a LiveKit token: it enforces room caps and audio-only publish limits. But the drop-in set `LIVEKIT_JWT_BIND=:8071`, which means **all interfaces**. Any LAN or VPN host, or a compromised container, could `POST http://10.10.10.29:8071/sfu/get` and get an **unguarded** token. The guard is fail-open by design, so `:8071` is the only hard boundary. **This PR:** the setup steps and port table now use `LIVEKIT_JWT_BIND=127.0.0.1:8071`. The guard already calls `http://127.0.0.1:8071` (`GUARD_UPSTREAM`), so nothing else changes. **To apply on LXC 151:** ```sh printf '[Service]\nEnvironment=LIVEKIT_JWT_BIND=127.0.0.1:8071\n' > /etc/systemd/system/lk-jwt-service.service.d/override.conf systemctl daemon-reload && systemctl restart lk-jwt-service ss -ltnp | grep 8071 # expect 127.0.0.1:8071 # from another LAN host: nc -zv 10.10.10.29 8071 → refused; a call still connects via :8070 ``` `LIVEKIT_JWT_BIND` is handed to Go's `http.ListenAndServe` upstream, so `host:port` works. I couldn't run the real binary locally (the dev stack uses a stand-in), so please check with `ss` after applying. **Not covered:** the issue also flags LiveKit metrics `6789`, Hookshot `9004`, node_exporter `9100` and the matrix-admin exporter `9101` on `0.0.0.0`. Restricting those depends on where Prometheus scrapes from, so I left them. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared added 1 commit 2026-10-18 01:27:01 -04:00
docs(livekit): bind lk-jwt-service to 127.0.0.1:8071, not all interfaces (#24)
Lint / Shell (shellcheck) (pull_request) Successful in 19s
Lint / JS (eslint) (pull_request) Successful in 16s
Lint / No secrets in webhook configs (pull_request) Successful in 9s
Lint / Landing page is rendered (matrix (pull_request) Successful in 5s
Lint / Python (ruff) (pull_request) Successful in 5s
Lint / Python deps (pip-audit) (pull_request) Successful in 38s
Lint / Secret scan (gitleaks) (pull_request) Successful in 8s
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 9s
Lint / No secrets in webhook configs (push) Successful in 4s
Lint / Landing page is rendered (matrix (push) Successful in 4s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 40s
Lint / Secret scan (gitleaks) (push) Successful in 7s
076340227f
voice-limit-guard (:8070) is meant to be the only way to get a LiveKit
token, but lk-jwt-service bound :8071 on every interface, so any LAN
host could mint an unguarded token (no max_users, full publish sources
in audio-only rooms). The guard runs on the same LXC: document the
loopback bind in the setup steps and the port table.

Refs #24

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared merged commit 070a94d0d7 into main 2026-10-18 19:45:48 -04:00
Sign in to join this conversation.