From 5085f8ab5530ca4784fc26dc98ebce25044977e1 Mon Sep 17 00:00:00 2001 From: Brandyn / Techy Date: Sat, 31 Oct 2026 15:46:25 -0500 Subject: [PATCH] Docs/apply note: MediaMTX does not hot-reload auth settings; restart between streams after auth changes Co-Authored-By: Claude Fable 5.1 --- README.md | 5 +++-- STATUS.md | 1 + configure.py | 5 +++-- dock/index.html | 8 +++++++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ee0c46c..ff9b960 100644 --- a/README.md +++ b/README.md @@ -289,8 +289,9 @@ MediaMTX asks dumpd (`POST /mtx-auth` on 127.0.0.1:8081, reachable only from Doc connection. Reads/playback are allowed (viewers are gated by Caddy + Authentik). Publishing needs a token minted by `GET /me/stream-token` behind Authentik for a member of `streamers`/`admins`/`media-admins`; dumpd checks the HMAC signature (`/etc/vanguard/stream-token.secret`, generated into `.env` as `STREAM_TOKEN_SECRET`), -the expiry, and that the path starts with that user's name. Changing this needs **no MediaMTX restart**: -MediaMTX hot-reloads `mediamtx.yml`; `configure.py` reloads Caddy in place and only restarts copyparty. +the expiry, and that the path starts with that user's name. MediaMTX hot-reloads paths/recording settings +but **not** the auth section: after changing auth, `docker compose restart mediamtx` between streams. +`configure.py` reloads Caddy in place and restarts only copyparty. ## Layout on the server diff --git a/STATUS.md b/STATUS.md index 82d260b..6e12202 100644 --- a/STATUS.md +++ b/STATUS.md @@ -85,6 +85,7 @@ Source of truth: this repo, `techy/Media-Server-Setup` on the stack's own Gitea - Several videos inside one non-season folder = ONE Jellyfin episode with "versions". Streams are therefore published flat as `__<ts>.mp4` in the streamer's folder (plugin 0.1.3 parses the title from the name). Four or five helmet cams a night each get their own episode. - The sweep's VFR check used a gawk-only function; Debian's mawk made it pass everything silently. Portable now. - A deploy block that is only half-run leaves old binaries in `/usr/local/bin`; `grep -c` the installed script before blaming logic. +- MediaMTX hot-reloads `paths`/recording settings but NOT `authMethod`/auth settings: those need a container restart (between streams). - MediaMTX stamps recording filenames in its container clock: without `TZ` it is UTC and the plugin reads names as Eastern (4 h off). `TZ=America/New_York` is set on the container. - MediaMTX 1.21 refuses to start without `webrtcAdditionalHosts` or `webrtcIPsFromInterfaces`; configure.py writes the public host in. - Jellyfin honours provider-supplied season numbers on a Shows library (day seasons appeared). Next check: Monday 04:10 ET should fold them into a week season. diff --git a/configure.py b/configure.py index 0a1c76a..c850452 100755 --- a/configure.py +++ b/configure.py @@ -358,7 +358,7 @@ srtAddress: :8890 # ---- auth ------------------------------------------------------------- # Publishing is authorised by dumpd (/mtx-auth) with short-lived tokens minted for Discord-authenticated # members of the streamers group. Reads are allowed; viewers are gated by Caddy + Authentik. No passwords. -# MediaMTX hot-reloads this file: changing auth needs no restart. +# NOTE: MediaMTX hot-reloads paths/recording settings but NOT the auth section — restart after auth changes. authMethod: http authHTTPAddress: http://{auth_gw}:8081/mtx-auth authHTTPExclude: @@ -469,7 +469,8 @@ def apply(domain, admin_pw, streamers, editors, auth_host="", watch_host="", dis run(dc + ["up", "-d", "--build"]) # recreates only services whose compose definition changed run(dc + ["restart", "copyparty"]) # copyparty re-reads its config on start run(dc + ["exec", "caddy", "caddy", "reload", "--config", "/etc/caddy/Caddyfile"]) # zero-downtime - print(" (mediamtx hot-reloads mediamtx.yml itself — live streams are not interrupted)") + print(" mediamtx: hot-reloads most of mediamtx.yml, but NOT auth changes. If you changed auth settings, run") + print(" docker compose restart mediamtx between streams (cuts a live recording).") def show(domain, admin_pw, streamers, editors, auth_host="", watch_host="", git_host="", bot_host="", live_host=""): print(f"\n== domain : {domain or '(not set)'}") diff --git a/dock/index.html b/dock/index.html index a2be380..9b21914 100644 --- a/dock/index.html +++ b/dock/index.html @@ -216,7 +216,13 @@ $("signout").onclick = async e => { const auth = "https://" + location.hostname.replace(/^[^.]+\./, "auth.") + "/if/flow/default-invalidation-flow/?next=" + encodeURIComponent(location.origin + "/dock/"); setTimeout(() => location.replace(auth), 400); }; -whoami(); renderPreview(); +// On load: who am I, and mint a token right away so the preview and the manual section show real values. +(async () => { + await whoami(); + try { await mint(); status("ready"); } + catch (e) { status(e.message, "bad"); $("m_tok").textContent = "— " + e.message; } +})(); +renderPreview(); </script> </body> </html>