| .. | ||
| build.sh | ||
| Dockerfile | ||
| README.md | ||
| standalone-publication.patch | ||
MatrixRTC standalone publication policy (iscg policy1)
Policy and boundary
This is a narrow fork of Element's lk-jwt-service v0.9.0, upstream commit
0e176b1eca44e67b11484d0bdf56999807bf2b8e (AGPL-3.0-only). It fixes both
standalone endpoints, /sfu/get and /get_token:
- Matrix OpenID verification still runs, including the subject's server name and the claimed user ID where the protocol supplies one.
- Every successfully authenticated participant may publish audio/video in the requested, room-scoped session, regardless of their homeserver.
LIVEKIT_FULL_ACCESS_HOMESERVERS=iscg.devstill gates the server-sideCreateRoomcall and delayed-leave delegation. It is NOT widened toastr.toor*. No user's JWT gains room creation, list, recording or admin privileges.- Existing application-service membership checks, when configured, are unchanged.
- The SFU MUST retain
room.auto_create: false. Otherwise remote users can create arbitrary SFU rooms by joining, regardless of JWT-service policy. - A remote user may obtain a scoped token before a local user creates the room; the SFU rejects joining a missing room. This is intentional upstream behaviour.
- Existing one-hour token TTL, SFU participant limits and container hardening are preserved. No new appservice/admin credential is introduced.
This is not Matrix room-membership authorization. On Heather, Tuwunel 1.9.4 has no MSC4502/MSC4512 integration, and lk-jwt-service is standalone. Someone with valid Matrix OpenID and knowledge of a room ID can request an SFU token even if not a Matrix member, including for an unencrypted call. This limitation existed for subscribing before the patch and now includes publishing. Room IDs are not authorization secrets; E2EE, when enabled by clients, protects media confidentiality, not resource abuse or forged room participation. Do not advertise this deployment as membership-checked or suitable for anonymous guests.
The fuller migration is homeserver-backed MSC4195/MSC4502/MSC4512 integration
with scoped application-service membership checks. It requires a homeserver
that supports those APIs (or a separately reviewed Tuwunel implementation),
client compatibility checks and a backed-up migration. Adding astr.to or *
to the full-access list does not solve membership authorization. The newer
upstream LIVEKIT_REMOTE_CAN_PUBLISH_HOMESERVERS option applies to federated
application-service requests, not to these standalone endpoints.
Source and tests
standalone-publication.patch changes two authorization arguments, adds a
startup policy banner, regression tests and updates the two HTTP integration
suites' remote publication expectations. Creation, delegation, OpenID and
membership-check implementations are not replaced.
The image build fails unless all root-library unit tests and both HTTP/OpenID
integration suites (get_token, sfu_get) pass. Regressions cover local users,
astr.to, an unrelated server, rejected OpenID, foreign/forged subject,
room-scoped JWTs and lack of creation/admin permissions. Existing membership
and delayed-event denial tests remain part of the unit suite.
The upstream archive, patch and Rust builder image are SHA256-pinned, and Cargo
uses --locked. Alpine build-tool packages are fetched from its package
repository, so this is a pinned-source build recipe, NOT a claim of bit-for-bit
reproducible output. Preserve the exported release image and its checksum too.
Build (Linux amd64 / Docker)
From this directory:
# Run long work in tmux. No production secrets are needed by the build.
sudo bash build.sh
The resulting image is
iscg/lk-jwt-service:0.9.0-policy1-6e21c58c02d6.
The image is local-only and Compose uses pull_policy: never. On a replacement
host, rebuild it or load the preserved Docker image archive BEFORE starting
Arion. Do not replace it with an unreviewed latest tag. Tests and compiler run
in build containers; no Rust toolchain is installed on the NixOS host.
Deployment and rollback
Deploy only matrix-rtc-jwt with the evaluated Arion composition, after staging
and health/token/media checks. No homeserver, SFU, Coturn or unrelated service
restart is required. Compare the Nix source baseline to /run/current-system
and inspect dry activation before switching so unrelated edits are not applied.
The deployment receipt records the exact image ID and new Nix generation. Before deployment preserve the old generation, old composition, old image, container start-time baseline and config source. Keep release archives outside cache on Heather and Poppy.
For an emergency rollback, use the saved pre-policy Arion composition:
sudo arion --prebuilt-file /path/from/receipt/old-compose.yaml \
up -d --no-deps --pull never matrix-rtc-jwt
Then restore the pre-policy Nix generation/source selectively, retaining any
subsequent unrelated edits. Do not restart the whole heather.service, wipe
volumes, revert the homeserver database or disable TLS verification. Rejoin the
call to obtain a fresh JWT; previously issued tokens do not change retroactively.