LIVEKIT_KEY/LIVEKIT_SECRET were committed in the unit since 68a6acf
(2026-06-12). That secret signs re-issued SFU join tokens, so it
controlled who could publish. Rotated and moved to /etc/matrix-deploy.env
(0600); livekit-server, lk-jwt-service and voice-limit-guard all updated
and verified against the new value.
Environment= overrides EnvironmentFile= regardless of order, so the
hardcoded lines had to be removed rather than shadowed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add a fail-open Python sidecar (livekit/voice-limit-guard.py) that fronts
lk-jwt-service to enforce per-room voice participant caps for ALL Matrix
clients, not just Lotus Chat:
- lk-jwt-service moved to :8071 (systemd drop-in), guard owns :8070 so NPM's
existing /sfu/get + /get_token proxy targets are unchanged
- guard reads io.lotus.voice_limit.max_users (Synapse admin API, cached),
forwards to lk-jwt-service, and on an issued token decodes the LiveKit alias
+ requester, counts distinct Matrix users via LiveKit ListParticipants, and
returns 403 when the room is full (rejoins/extra devices allowed)
- any error fails open (returns upstream response) so calls never break
- systemd/voice-limit-guard.service; README documents ports, setup, revert
Also update landing page: voice limit is now server-enforced for all clients.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>