STATUS/plan: phases 5-7 and 11 live and verified; refreshed unfinished list

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 15:48:33 -05:00
parent 5085f8ab55
commit a7ad3dc224
2 changed files with 23 additions and 27 deletions

View File

@@ -180,7 +180,7 @@ Checklist:
- [ ] Medal local filename pattern → add to `ItemTimestamp` (need a sample filename)
- [ ] later: serve `dist/` at `/plugins/` via Caddy as a plugin repo; theme CSS
### Phase 5 — copyparty behind Authentik (built; apply pending)
### Phase 5 — copyparty behind Authentik ✅ live
- [ ] Authentik → Providers → Proxy provider, *forward auth (single application)*, external host
`https://ovh1.HOST`; Application bound to it; add to the embedded outpost
- [ ] Caddy: `forward_auth 127.0.0.1:9000 { uri /outpost.goauthentik.io/auth/caddy; copy_headers X-Authentik-Username X-Authentik-Groups … }`
@@ -194,13 +194,13 @@ Checklist:
- [x] decided: no WebDAV (Discord login only); browser downloads
- [ ] policy on the Application: only `editors` + `admins` + `streamers` may pass
### Phase 6 — Syncthing UI + dump behind Authentik (built together with phase 5; apply pending)
### Phase 6 — Syncthing UI + dump behind Authentik ✅ live
- [ ] `/sync/`: forward-auth, policy `admins` only; Syncthing GUI auth can stay as a second layer
- [ ] `dumpd.py`: read `X-Authentik-Username` / `X-Authentik-Groups` from Caddy instead of basic auth;
admin = member of `admins`; drop `dump-users.txt`
- [ ] dock: `Dump tonight` sends no credentials; session cookie carries identity
### Phase 7 — dock polish + cleanup (built with phase 11; apply pending)
### Phase 7 — dock polish + cleanup ✅ live (dock mints tokens; no stored credentials)
- [ ] `dumpd.py` gains `GET /me` → `{user, groups, stream_key}` for the logged-in streamer;
dock fills OBS settings from it — nobody types a stream password again
- [ ] `configure.py` shrinks: hostnames + streamers only (editors and admin live in Authentik)
@@ -263,7 +263,7 @@ 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) (built; apply pending)
### Phase 11 — MediaMTX auth through Authentik (no stream keys anywhere) ✅ live
Implemented variant: **short-lived HMAC tokens minted by dumpd** for Discord-authenticated members of
`streamers` (no Authentik app passwords — "Discord only" decision). Dock and portal mint a token per Go Live;
manual setups get it from the dock's accordion. MediaMTX `authMethod: http` → dumpd `/mtx-auth` on 8081

View File

@@ -1,6 +1,6 @@
# Vanguard stack — what runs, what people do, what's unfinished
Living document. Updated whenever something is deployed or changes behaviour. Last update: 2026-10-31.
Living document. Updated whenever something is deployed or changes behaviour. Last update: 2026-10-31 (evening).
Host: `ovh1.dumpstervigilantes.rip` (OVH SYS-1, Debian 13). Bundle: `~/vanguard-stream` on the box.
Source of truth: this repo, `techy/Media-Server-Setup` on the stack's own Gitea (`ssh://git@git.dumpstervigilantes.rip:2222/techy/Media-Server-Setup.git`).
@@ -25,11 +25,11 @@ Source of truth: this repo, `techy/Media-Server-Setup` on the stack's own Gitea
| Who | Activity | Where | Login |
|---|---|---|---|
| Streamer | Type a title (live preview + naming rules), Go Live, Stop. "Dump tonight" if it was junk (3-day undo). Manual-setup accordion with endpoints and a hidden token | OBS browser dock `https://ovh1…/dock/` | Discord login in the dock (once); dock mints a 12 h token per Go Live — **no passwords** (pending apply) |
| Streamer | Type a title (live preview + naming rules), Go Live, Stop. "Dump tonight" if it was junk (3-day undo). Manual-setup accordion with endpoints and a hidden token | OBS browser dock `https://ovh1…/dock/` | Discord login in the dock; dock mints a 12 h token per Go Live — **no passwords, verified live** |
| Gamer | Nothing; clips save where they always did | their clipper + Syncthing, paired once | — |
| Editor | Browse by streamer/title, scrub in browser, download originals, upload finals | copyparty `https://ovh1…/` | Discord (Authentik); rights by group `editors` / `media-admins` — **pending apply** |
| Editor | Browse by streamer/title, scrub in browser, download originals (zip/tar for folders), upload finals | copyparty `https://ovh1…/` | Discord (Authentik); rights by group `editors` / `media-admins` |
| Anyone in the Discord server | Watch recordings and clips by streamer and season | Jellyfin `https://watch.…/` | Discord (Authentik) |
| Anyone in the Discord server | Watch live: all active streams in dockable windows, audio follows focus, per-window mute/volume | Live portal `https://live.…/` | Discord (Authentik, domain-level) — live; viewer side not yet exercised during a stream |
| Anyone in the Discord server | Watch live: all active streams in dockable windows, audio follows focus, per-window mute/volume | Live portal `https://live.…/` | Discord (Authentik, domain-level) — **live, shows a real stream** |
| Streamer (Windows) | **Go Live** from the browser: pick the WarDogs window (+audio on Windows Chrome 141+; Linux/Mac video only), streams as `<user>/HelmetCam-<date>`; no OBS needed | Live portal → Go Live | Discord; key fetched for the logged-in user — **verified end to end** (publish → `.live` → sweep → title folder) |
| Devs | Host code, review, CI | Gitea `https://git.…/`, ssh 2222 | **local account** (Discord later) |
| Bot dev | Push code, restart container, read logs; web UI at `https://bot.…/` | Gitea + compose; `bot/AGENT.md` | web UI behind Discord (Authentik), once its provider exists |
@@ -43,10 +43,10 @@ Source of truth: this repo, `techy/Media-Server-Setup` on the stack's own Gitea
| Service | Role | State |
|---|---|---|
| MediaMTX | RTMP/SRT ingest, records fMP4; publish auth delegated to dumpd (tokens) | live; auth switch **pending apply** (hot-reload, no restart) |
| copyparty | browse/scrub/download/WebDAV/finals upload | behind Authentik, group permissions — **built, pending apply** (currently local accounts) |
| dumpd + dock | dump-tonight endpoint, OBS dock page | identity from Authentik headers — **built, pending apply** |
| Syncthing | clip intake, UI at `/sync/` | UI behind Authentik + `media-admins` — **built, pending apply** |
| MediaMTX | RTMP/SRT ingest, records fMP4; publish auth delegated to dumpd (tokens via `/mtx-auth`) | live, token auth verified |
| copyparty | browse/scrub/download/finals upload | behind Authentik, group permissions (`editors`, `media-admins`), Discord-only, no WebDAV | live |
| dumpd + dock | dump, stream tokens, MediaMTX auth hook; OBS dock | identity from Authentik headers | live |
| Syncthing | clip intake, UI at `/sync/` | UI behind Authentik + `media-admins` | live |
| normalize sweep | editing standard, one copy per clip | live |
| nftables | host firewall (22, 80/443, 1935, 2222, 3306, 8890/udp, 22000) | live |
| Caddy | TLS + routing for all hostnames | live |
@@ -62,21 +62,17 @@ Source of truth: this repo, `techy/Media-Server-Setup` on the stack's own Gitea
## Unfinished, in rough priority
1. **MediaMTX container recreate** for `TZ=America/New_York` (filenames were UTC-stamped) and `moq: no` — `docker compose up -d --force-recreate mediamtx` after the compose upload.
1b. Authentik `discord-roles-to-groups` policy + `bot-users` group (`bot` CNAME now correct).
1c. Confirm plugin 0.1.2 installed and runner registered.
1d. Watch a real stream from a second browser: corner chip should say `webrtc`; confirm WarDogs audio came through.
2. **Register the runner** (`./registerGiteaRunner.sh`).
3. **`bot` CNAME + Authentik proxy provider** — first use of forward-auth; proves the pattern for copyparty.
4. **Apply phase 5+6** (copyparty, dock, dump, /sync behind Authentik; group permissions). Authentik side: group `media-admins` with techy in it. Decision: Discord login only → no WebDAV; browser downloads (zip/tar) instead.
5. **Apply phase 7+11** (token publish auth): `configure.py` apply (MediaMTX hot-reloads; no stream interruption), new dumpd + unit, firewall rule for 8081 from Docker, dock upload, portal deploy. Then every streamer must be in the Authentik `streamers` group.
6. **Gitea login via Authentik** (OIDC source, auto-register, `admins` → Gitea admin).
7. **Housekeeping**: pin `AUTHENTIK_TAG` in `.env`, rotate the Discord client secret that was in a screenshot, nightly Postgres dump, Jellyfin login branding (Discord button first), check a non-admin Discord user's Jellyfin view.
8. **Medal filename pattern** in the plugin's timestamp parser — need one sample filename.
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.
13. **SYS-3** when transcoding or sweep speed hurts: Quick Sync, flip the plugin's policy toggle off.
1. Authentik: `discord-roles-to-groups` policy so `streamers`/`editors`/`media-admins`/`bot-users` follow Discord roles (`bot-users` group needed for the bot host). Set the provider's Invalidation flow to `default-provider-invalidation-flow` so every logout forces a full re-login.
2. Confirm plugin 0.1.3 under Jellyfin → Plugins and the Gitea runner registered.
3. Portal viewer during a real stream: corner chip `webrtc`; Windows Go Live with WarDogs audio (first Windows streamer).
4. Gitea login via Authentik (plan phase 10).
5. Housekeeping: pin `AUTHENTIK_TAG`, rotate the Discord client secret seen in a screenshot, nightly Postgres dump, Caddyfile formatting warning.
6. Medal filename pattern in the plugin (need a sample filename).
7. Home archive puller on the home box.
8. Plugin repository served by Caddy so Jellyfin updates from its catalog.
9. Clip submissions (belongs to the bot). Bot code from the other dev.
10. Authentik blueprint from `.env` (Discord source, groups, policies, provider) for reproducible installs.
11. SYS-3 when transcoding or sweep speed hurts.
## 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.