Plan: phase 11 — MediaMTX auth via Authentik (JWT for the browser, app passwords for OBS, no stream keys)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 00:58:50 -05:00
parent 4b4c7eaedf
commit f06ebc1ec1
2 changed files with 22 additions and 1 deletions

View File

@@ -261,6 +261,26 @@ Same pattern as Jellyfin: Authentik is the identity, Gitea trusts it.
- [ ] policy on the Authentik application: who may reach Gitea at all (e.g. `admins` + a `devs` group)
- [ ] test with a non-admin Discord user; confirm admin mapping via `admins` group
### Phase 11 — MediaMTX auth through Authentik (no stream keys anywhere)
Goal: nobody holds a MediaMTX password. "May publish" = Authentik identity + `streamers` group (filled by
Discord roles); the publish path must start with the user's own name.
- MediaMTX `authMethod: http`, `authHTTPAddress: http://127.0.0.1:8080/mtx-auth` (dumpd becomes the
arbiter; reads stay open to `any`, Caddy gates viewers). MediaMTX posts user/pass/token/action/path/ip.
- **Browser (Go Live, WHEP)**: Caddy forwards Authentik's `X-Authentik-Jwt` as `Authorization: Bearer` on
the `/webrtc` hop. dumpd verifies the JWT against Authentik's JWKS (`/application/o/<slug>/jwks/`),
reads `preferred_username` + `groups`, allows publish iff `path` starts with `<username>/` and user ∈ streamers.
No `/me/stream-key`, no `streamers.json`, nothing in the browser.
- **OBS**: streamer creates an **app password** in their Authentik profile and pastes it in the dock once;
dumpd validates Basic `user:app-password` against Authentik (outpost basic-auth endpoint or the API),
same path rule. Revoking the app password revokes the stream key.
- configure.py loses the streamers section (folders are created on first publish by MediaMTX anyway;
the sweep and Jellyfin cope). Dock: "paste your Authentik app password" instead of a stream password.
- [ ] dumpd `/mtx-auth` (JWT via JWKS, Basic via Authentik, path rule, 5 s cache)
- [ ] Caddy: `header_up Authorization "Bearer {http.request.header.X-Authentik-Jwt}"` on `/webrtc/*` (replaces X-Stream-Auth)
- [ ] MediaMTX `authMethod: http`; keep `any` read; drop `authInternalUsers`
- [ ] dock + README; remove streamers from configure.py; delete `streamers.json`
- [ ] test: OBS with an app password; Go Live with no key; a non-streamer gets denied
### Option — more clip sources (Medal, Twitch/YouTube/Kick clips, Discord uploads)
Today the only clip intake is a local clipper folder synced by Syncthing. Members without that

View File

@@ -76,7 +76,8 @@ Source of truth: this repo, `techy/Media-Server-Setup` on the stack's own Gitea
9. **Home archive puller** on the home box.
10. **Plugin repository** served by Caddy so Jellyfin updates the plugin from its catalog.
11. **Clip submissions** (Medal/Twitch/YouTube links, Discord uploads) — belongs to the bot.
12. **SYS-3** when transcoding or sweep speed hurts: Quick Sync, flip the plugin's policy toggle off.
12. **MediaMTX auth through Authentik** (plan phase 11): no stream keys; Go Live uses the Authentik JWT, OBS uses an Authentik app password; "streamer" = group membership from a Discord role.
13. **SYS-3** when transcoding or sweep speed hurts: Quick Sync, flip the plugin's policy toggle off.
## Verified behaviours worth remembering
- **Never scp generated configs** (`mediamtx.yml`, `copyparty.conf`, `Caddyfile`, `dump-users.txt`, `.env`): a template copy wiped all streamers once. They are gitignored now; `*.example.*` are reference only.