Files
Media-Server-Setup/HOSTNAME-CHANGE.md

11 KiB

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 /), files (copyparty), clips, sync, live (portal + /dock/, /dock/clock/, /dump, /me, /time), auth, watch, git, bot. Ours: media., files., clips., sync., live., … under dumpstervigilantes.rip.

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:<role> markers)
.env MAIN_HOST, FILES_HOST, CLIPS_HOST, SYNC_HOST, WATCH_HOST, GIT_HOST, BOT_HOST, LIVE_HOST, APEX_HOST, APEX_REDIRECT
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). compose up -d in the apply recreates the affected containers (seconds each)
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. + the parent of the current host
dock/index.html auth. (sign-out), ingest host prefilled from the current host (live.; any name of the box works for RTMP/SRT)
switchToClone.sh, deployLive.sh defaults for git.dumpstervigilantes.rip / media.dumpstervigilantes.rip (override by env/arg, or edit)
README.md, FRESH-INSTALL.md examples only
Renaming a label (e.g. watch → video) means editing the first two; changing only the domain does not.

Outside the repo — must be changed by hand

System Setting Which host
DNS A record + CNAMEs all
Discord developer portal OAuth2 redirect https://AUTH/source/oauth/callback/discord/ auth
Authentik Embedded Outpost authentik_host auth
Authentik Vanguard sites proxy provider: authentication URL (auth) and cookie domain (base) auth, base
Authentik Jellyfin provider redirect URI https://WATCH/sso/OID/redirect/authentik watch
Authentik Gitea provider redirect URI https://GIT/user/oauth2/authentik/callback git
Jellyfin SSO-Auth plugin: OID endpoint https://AUTH/application/o/jellyfin/ auth
Jellyfin Branding login disclaimer (the form action contains the watch host) watch
Jellyfin Vanguard Metadata plugin: Public URL, Authentik URL watch, auth
Gitea Authentication source authentik: discovery URL https://AUTH/application/o/gitea/.well-known/openid-configuration auth
Gitea runner registered with the instance URL → ./registerGiteaRunner.sh again git
Server clone git remote set-url origin ssh://git@GIT:2222/techy/Media-Server-Setup.git; ~/.ssh/config.vanguard Host line git
Dev box git remote set-url origin … git
Streamers' OBS dock URL (Custom Browser Docks), dock Settings → ingest host (re-save), clock browser source URL (dock → Timecode band → "Add band + clock source" again), any manual RTMP/SRT configs (copy from the dock) live
Jellyfin apps on phones/TVs server address watch
Bookmarks, Discord pinned links main (gateway), clips, files, watch, live all
Not affected: Syncthing pairings (device IDs), MariaDB, stream tokens, the Gitea webhook (gateway IP), Authentik users/groups/policies.

A. Renaming one subdomain (example: watch.BASE → video.BASE)

  1. DNS: add CNAME video.BASE → HOST. Keep the old record until step 7.
  2. Server, between streams: ./configure.py --full → Enter keeps every value; type the new name at the "Jellyfin hostname" prompt; y. Caddy reloads (new block, old gone), Jellyfin is recreated with the new published URL. curl -sI https://video.BASE/ | head -1 → 200/302 once the certificate is issued. (Only the main host touches mediamtx.yml; other hosts need no MediaMTX restart.)
  3. Authentik: Applications → Providers → Jellyfin → Edit → redirect URI → the new host → Update.
  4. Jellyfin: Dashboard → General → Branding → disclaimer form action → new host → Save. Dashboard → Plugins → Vanguard Metadata → Public URL → new host → Save.
  5. If the label changed (watch→video), edit about/index.html (sub('watch') → sub('video')) — commit, push, sudo vanguard-deploy pull. (.env APEX_REDIRECT too if the bare domain pointed at it: ./configure.py --full.)
  6. Private window: https://video.BASE/ → Discord → in. The gateway https://HOST/ links to the new name.
  7. Remove the old DNS record. Tell members with Jellyfin apps to update the server address.

Per-host extras when it is a different host:

  • auth: Discord portal redirect; Authentik outpost authentik_host and the proxy provider's authentication URL; Jellyfin SSO plugin OID endpoint; Vanguard plugin Authentik URL; Gitea auth source discovery URL; dock/index.html + about/index.html if the label changed. Everyone re-logs in.
  • git: Authentik Gitea provider redirect; ./registerGiteaRunner.sh; server clone remote + ~/.ssh/config.vanguard; dev remote; switchToClone.sh default.
  • live, bot: only the compose env (automatic) and about/index.html if the label changed.
  • main (HOST): mediamtx.yml changes → docker compose restart mediamtx between streams; every streamer re-adds the dock URL, re-saves Settings (ingest host), and re-runs "Add band + clock source"; manual RTMP/SRT configs are re-copied from the dock; deployLive.sh default host.

B. Changing the base domain (everything at once)

Plan a maintenance window: Caddy, Jellyfin, Gitea, the bot and MediaMTX all restart, and every member logs in again (the Authentik session cookie is bound to the base domain).

  1. DNS on the new domain: A HOST2 → IP, CNAMEs files, clips, sync, live, auth, watch, git, bot → HOST2 (optional bare domain A). Verify they resolve before continuing. Leave the old domain's records in place for now.
  2. Discord developer portal → OAuth2 → add redirect https://auth.NEW/source/oauth/callback/discord/ (keep the old one until step 9).
  3. Server, between streams: ./configure.py --full → new main hostname; the eight sub-hostnames default to the new base (Enter); bare domain; y. Then docker compose restart mediamtx (webrtcAdditionalHosts changed). All sites answer on the new names within a minute (certificates).
  4. Authentik (log in at the NEW auth host with akadmin — Discord login is broken until step 5 is done):
    • Outposts → Embedded Outpost → authentik_host: https://auth.NEW
    • Providers → Vanguard sites → authentication URL https://auth.NEW, cookie domain NEW
    • Providers → Jellyfin → redirect https://watch.NEW/sso/OID/redirect/authentik
    • Providers → Gitea → redirect https://git.NEW/user/oauth2/authentik/callback
  5. Private window: https://auth.NEW/ → Discord login works (the redirect from step 2 is used).
  6. Jellyfin: SSO plugin OID endpoint https://auth.NEW/application/o/jellyfin/; Branding disclaimer form action https://watch.NEW/sso/OID/start/authentik; Vanguard plugin Public URL + Authentik URL. Test the SSO start URL.
  7. Gitea: auth source discovery URL https://auth.NEW/application/o/gitea/.well-known/openid-configuration; ./registerGiteaRunner.sh; server: cd ~/vanguard-stream && git remote set-url origin ssh://git@git.NEW:2222/techy/Media-Server-Setup.git and edit ~/.ssh/config.vanguard (Host line); dev box: git remote set-url origin …. Test sudo vanguard-deploy pull.
  8. Repo defaults: switchToClone.sh (REPO_SSH), deployLive.sh (HOST) — commit, push, pull.
  9. Streamers: re-add the dock at https://live.NEW/dock/, re-save Settings, "Add band + clock source" again. Members: https://HOST2/; Jellyfin apps → new server address. Remove the old Discord redirect and the old DNS.

C. Splitting the single main host into media / files / clips / sync (done 2026-11-01)

Before: one main host (ovh1.BASE) served copyparty at /, /about/, /clips/, /sync/, /dock/, /dump, /time. After: media.BASE = gateway at /; files.BASE = copyparty; clips.BASE; sync.BASE; live.BASE gains /dock/, /dock/clock/, /dump, /me, /time, /whoami. /time is only on live because the two pages that fetch it (the clock source and Go Live) are same-origin there. Authentik needs nothing: the domain-level provider covers every name under BASE, the outpost host (auth.) is unchanged.

  1. DNS: CNAMEs media, files, clips, sync → the box (keep ovh1 for ssh; it is no longer a web host).
  2. Dev box: pull/upload the repo (configure.py, about/, addCommunityMediaServer.sh, docs).
  3. Server, between streams: ./configure.py --full → main hostname media.BASE; Enter for the sub-hostnames (defaults files., clips., sync., …); bare domain redirect → https://media.BASE/; y. Then docker compose restart mediamtx (webrtcAdditionalHosts is now media.) and ./deployLive.sh (portal build picks up nothing new, but confirms /srv/live is served on live.).
  4. Streamers: OBS → Custom Browser Docks → replace the dock URL with https://live.BASE/dock/; dock Settings → save; Timecode band → "Add band + clock source" again (the clock browser source URL moved).
  5. Discord: re-pin https://media.BASE/ (members), https://clips.BASE/ (gamers), https://files.BASE/ (editors).
  6. Old ovh1 bookmarks stop working (no Caddy block, TLS fails) — point people at the gateway.

Checklist after any change

dev$ for h in HOST files.BASE clips.BASE sync.BASE live.BASE auth.BASE watch.BASE git.BASE bot.BASE; do printf '%-26s ' $h; curl -s -o /dev/null -m 10 -w '%{http_code}\n' https://$h/; done
https://HOST/whoami            → your identity (gate works on the new name)
https://watch.BASE/sso/OID/start/authentik   → Jellyfin SSO round trip
https://git.BASE/user/login    → "Sign in with authentik" round trip
dock → Go Live → journalctl -u dumpd | grep mtx-auth   → allow publish
live.BASE → a window appears for the test stream, chip "webrtc"