# Changing hostnames safely Two cases: renaming one subdomain (e.g. `watch.BASE` → `video.BASE`), and moving the whole stack to a new base domain. Both are mostly `configure.py --full` plus a known list of places outside the repo that hold the name. Do it between streams: the main host is MediaMTX's WebRTC advertised host, so a main-host change needs a MediaMTX restart. Roles: `main` (gateway page at `/`, `/onboarding/`), `files` (copyparty), `clips`, `sync`, `live` (portal + Go Live, `/dock/`, `/dock/clock/`, `/dump`, `/me`, `/time`, `/whoami`), `auth`, `watch`, `git`, `bot`, `diag` (Kibana at `/`, `/streaming`, `/disk`, dumpd's `/streaming/api/*`), and optionally `apex` (the bare domain, a redirect to `APEX_REDIRECT`; it needs its own A record at the box or Caddy cannot get its certificate — as of 2026-11-06 the bare `dumpstervigilantes.rip` resolves elsewhere, so leave `APEX_HOST` empty or fix the record first). Ours: `media.`, `files.`, `clips.`, `sync.`, `live.`, `diag.`, … under `dumpstervigilantes.rip`. `ovh1.BASE` is ssh only. ## The one rule: apps before Authentik Change the app, then Authentik, never the other way round. An app that already lives on its new name but whose Authentik provider still says the old one is simply unreachable until Authentik is updated; a provider pointed at a name the app does not answer on yet locks you out of the app, and if that app is the gate in front of the admin UI, out of everything. So in every procedure below Authentik comes after the servers, the containers, Jellyfin and Gitea — and the Discord developer portal after Authentik. The safety net at every step is akadmin's password card, `https://AUTH/if/flow/default-authentication-flow/?admin=1`, which bypasses the Discord forward. Note that `configure.py --apply` does touch Authentik on its own: the login redirect stage's target (the Discord source's login URL on the auth host) and the brand's default application. Both are Authentik-internal, neither decides whether an app is reachable, and the admin card ignores the redirect stage — so they cannot lock you out. The things that can — outpost host, proxy provider external host and cookie domain, Jellyfin/Gitea redirect URIs — are never changed by any script here. ## Where hostnames live ### Generated on the server by `configure.py` (regenerated by `--full`, nothing to edit by hand) | Place | Holds | |---|---| | `Caddyfile` | every site block — the source of truth `configure.py` reads back (`# vanguard:` markers) | | `.env` | `MAIN_HOST`, `FILES_HOST`, `CLIPS_HOST`, `SYNC_HOST`, `DIAG_HOST`, `WATCH_HOST`, `GIT_HOST`, `BOT_HOST`, `LIVE_HOST`, `APEX_HOST`, `APEX_REDIRECT`; during a move `ALT_BASE` (every site also answers under it) and `REDIRECT_BASE` (old names 308 to the new) | | `mediamtx.yml` | `webrtcAdditionalHosts: [MAIN_HOST]` (needs a MediaMTX restart to take effect) | | `docker-compose.yml` → container env | Jellyfin `PublishedServerUrl` (WATCH), Gitea `DOMAIN/ROOT_URL/SSH_DOMAIN` (GIT), bot `WEB_PUBLIC_URL` (BOT), MediaMTX `LIVE_HOST` (text of the "is live" post), act_runner `GITEA_INSTANCE_URL` (GIT), Kibana `server.publicBaseUrl` via `DIAG_HOST` (DIAG). `compose up -d` in the apply recreates the affected containers (seconds each). MediaMTX is on the host network and is deliberately **not** recreated by the apply | | Authentik, by `configure.py --apply` (`--ak-branding` alone) | the login **redirect stage** target `https://AUTH/source/oauth/login//` (members never see an Authentik page), the brand's default application (the proxy provider whose external host is MAIN), logo/favicon/background paths (relative, no host). Re-run after an **auth** or **main** change | | Kibana landing dashboard, by `configure.py --apply` (`KEY=… kibana-setup.py landing` alone) | the Vanguard tile's links: LIVE, FILES, WATCH, MAIN, GIT, BOT, SYNC from `.env`, AUTH derived as `auth.`; `/streaming`, `/disk` relative. Re-run after any change | | Caddy TLS | certificates for new names are fetched automatically; old ones linger harmlessly | ### Pages in the repo that derive sibling hosts from the browser's location (label names hard-coded) | File | Assumes | |---|---| | `about/index.html` | `files.`, `clips.`, `sync.`, `live.`, `auth.`, `watch.`, `git.`, `bot.`, `diag.` + the parent of the current host (`sub('