From 1ee8befdeeb730e458119c07b52f0c77cc77b503 Mon Sep 17 00:00:00 2001 From: Brandyn / Techy Date: Mon, 2 Nov 2026 21:57:52 -0600 Subject: [PATCH] install.sh, deploy.sh and the runbooks cover the bot bundle path install.sh installs deployBotBundle.sh as vanguard-deploy-bot and creates /srv/bot/app; the pipeline reinstalls it when it changes. FRESH-INSTALL gains section 7a and appendix L (the first release, the python312 runner label, the Gitea secrets, the Authentik app), with the appendix relettered so it stays in order. README's rebuild list says the bot's repo is outside this one and what to restore where. Co-Authored-By: Claude Opus 5 (1M context) --- FRESH-INSTALL.md | 44 ++++++++++++++++++++++++++++++++++++++++---- HOSTNAME-CHANGE.md | 1 + README.md | 9 ++++++++- deploy.sh | 1 + install.sh | 3 ++- 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/FRESH-INSTALL.md b/FRESH-INSTALL.md index 71c7d23..9a928c9 100644 --- a/FRESH-INSTALL.md +++ b/FRESH-INSTALL.md @@ -7,6 +7,8 @@ README.md (section numbers given). ## 0. Before touching the server - DNS: `A` record for `HOST` → the server IP; `CNAME`s `files`, `clips`, `sync`, `live`, `auth`, `watch`, `git`, `bot` → `HOST`. Optional: the bare domain `A` → server IP (it redirects to `https://HOST/`). +- The Discord bot lives in its **own** repo (ours `VanguardOrg/VanguardBot`), not in this one. Nothing here + needs it to exist; section 7a wires it up afterwards. - Discord developer portal → New Application (one app serves Authentik login, the Jellyfin plugin's bot and the Discord bot): - OAuth2 → Redirects: `https://auth.BASE/source/oauth/callback/discord/` (the last segment is the Authentik @@ -103,6 +105,18 @@ Log in at `https://git.BASE/` as `GITEA_ADMIN_USER` / `GITEA_ADMIN_PASSWORD` fro (your SSH key under Settings → SSH keys). 3. Runner: `./registerGiteaRunner.sh` on the server → Site Administration → Actions → Runners shows it idle. +## 7a. Discord bot (README 5d) +1. The bot is **not** part of this repo. Its code arrives as a release bundle built by its own Gitea Actions + workflow and installed by `deployBotBundle.sh`; the image here carries no bot dependencies. +2. Create the org + repo in Gitea (ours: `VanguardOrg/VanguardBot`) and let the dev push to it. +3. The runner needs the **`python312`** label (CPython 3.12 + node, for the JavaScript actions). It is in + `docker-compose.yml`; labels are fixed at registration, so `./registerGiteaRunner.sh` after any change. +4. In Gitea → the bot repo → Settings → Actions: secrets `BOT_DEPLOY_SECRET` (from `./configure.py --show`) + and `DISCORD_BOT_TOKEN`; variable `DISCORD_GUILD_ID`. **The bot's secrets live here, not in `.env`.** +5. Authentik: a Proxy Provider for `https://bot.BASE` on the embedded outpost (same shape as `live.`). +6. Push to `main` → CI tests, builds the bundle, posts it signed to dumpd, which installs it and restarts the + container. By hand: `./deployBotBundle.sh `; back out with `--rollback`. + ## 8. Pipeline (README "Deployment") 1. On the server: `./switchToClone.sh key` → add the printed key as a read-only **Deploy Key** on the repo → `./switchToClone.sh clone` (keeps `.env`, generated configs, plugin zips) → `./configure.py --apply`. @@ -305,8 +319,30 @@ K2. dev$ ssh debian@HOST 'f=$(ls -t /srv/media/streams/*/*.mp4 | head -1); echo K3. https://watch.BASE/ → the recording is an episode under this weekday's season; Discord feed channel got a post with a frame grab. K4. https://live.BASE/ while someone streams → a window with the corner chip "webrtc". -## L. Afterwards +## L. Discord bot (first release) -L1. dev$ ssh debian@HOST 'docker inspect authentik-server --format "{{.Config.Image}}"' → put that tag in .env as AUTHENTIK_TAG, then ./configure.py --apply. -L2. Rotate anything pasted into a chat or screenshot (Discord client secret: portal → Reset → Authentik source → update). -L3. Backups: .env, /srv/appdata, /srv/media, /etc/vanguard/clip-quotas.json. Home archive puller: README §7. +L1. Gitea → New Organization `VanguardOrg` → New Repository `VanguardBot` (private). The bot dev pushes to it. +L2. dev$ ssh debian@HOST 'cd ~/vanguard-stream && ./configure.py --show | grep -A2 "bot ci"' + → copy BOT_DEPLOY_SECRET and the list of keys CI may set. +L3. Gitea → VanguardBot → Settings → Actions → Secrets → Add: `BOT_DEPLOY_SECRET` (L2), `DISCORD_BOT_TOKEN` (A2). + Variables → Add: `DISCORD_GUILD_ID` (A3). Optional `VANGUARD_DEPLOY_HOST` = the docker gateway from I3 if + the deploy job cannot detect it. +L4. Check the runner advertises the python312 label: + dev$ ssh debian@HOST 'cd ~/vanguard-stream && ./registerGiteaRunner.sh' (only if it does not) + Site Administration → Actions → Runners → vanguard-runner → labels include python312. +L5. Authentik → Applications → Create with provider → Proxy Provider, Forward auth (single application), + external host `https://bot.BASE` → add to the Embedded Outpost → bind group `bot-users`. +L6. The dev pushes to `main`. The run should end with the install log, "settings written: DISCORD_BOT_TOKEN, + DISCORD_GUILD_ID" and HTTP 200. + dev$ ssh debian@HOST 'cd ~/vanguard-stream && ./deployBotBundle.sh --status' + → version, commit, package count, container Up. +L7. dev$ ssh debian@HOST 'docker logs discord-bot --tail 20' + → the bot's version line, then its MariaDB connection. First real MariaDB run: watch for a retry loop. +L8. Private window → https://bot.BASE/ → Discord login → the bot's pages. Needs the `bot-users` group (admins + need it too, or set BOT_REQUIRE_GROUP= and let the bot's WEB_ALLOWED_GROUPS decide). + +## M. Afterwards + +M1. dev$ ssh debian@HOST 'docker inspect authentik-server --format "{{.Config.Image}}"' → put that tag in .env as AUTHENTIK_TAG, then ./configure.py --apply. +M2. Rotate anything pasted into a chat or screenshot (Discord client secret: portal → Reset → Authentik source → update). +M3. Backups: .env, /srv/appdata, /srv/media, /etc/vanguard/clip-quotas.json. Home archive puller: README §7. diff --git a/HOSTNAME-CHANGE.md b/HOSTNAME-CHANGE.md index 54b990f..b3da557 100644 --- a/HOSTNAME-CHANGE.md +++ b/HOSTNAME-CHANGE.md @@ -45,6 +45,7 @@ Renaming a *label* (e.g. `watch` → `video`) means editing the first two; chang | 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 | +| Gitea, the bot repo | nothing for a rename; `VANGUARD_DEPLOY_HOST` only if it was set to an address | — | | 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 | diff --git a/README.md b/README.md index 632f908..e32b47b 100644 --- a/README.md +++ b/README.md @@ -497,7 +497,8 @@ secret) are gitignored and survive pulls; static pages are bind-mounted from the | `configure.py`, `dock/`, `clips/`, `about/`, stignore | `configure.py --apply` → Caddy reload, copyparty restart | none / a second | | `bin/*`, `systemd/*` | install; dumpd restart when it changed; timers pick up next run | a second | | `firewall/nftables.conf` | `nft -f` | none | -| `docker-compose.yml`, bot image | `compose up -d --build` for changed services | that service | +| `docker-compose.yml`, `bot/Dockerfile`, `bot/entrypoint.sh` | `compose up -d --build` for changed services | that service | +| `deployBotBundle.sh` | reinstalled as `/usr/local/bin/vanguard-deploy-bot` (what dumpd runs for the bot's CI) | none | | anything that changes `mediamtx.yml` or the mediamtx service | **restart only when no stream is live**; otherwise deferred, `deploy-pending.timer` retries every 5 min | none while live | | `jellyfin-plugin-vanguard/dist/*.zip` (committed) | `installJellyfinPlugin.sh` | Jellyfin restart | | `live/` | `npm run build` on the server → `/srv/live` | none | @@ -561,6 +562,10 @@ Still manual on a truly fresh box (not in the repo; documented in §5c–5g): the domain-level proxy provider + outpost host, the Jellyfin and Gitea OIDC providers, application bindings - Jellyfin: first-run wizard, libraries (Shows + Vanguard provider), SSO plugin + provider, branding - Gitea: authentication source (authentik), deploy key, webhook; `./registerGiteaRunner.sh` +- Discord bot: its repo lives outside this one, so nothing here restores it. Put `BOT_DEPLOY_SECRET` + (`./configure.py --show`), `DISCORD_BOT_TOKEN` and `DISCORD_GUILD_ID` into that repo's Gitea Actions + secrets/variables, then push to its `main` — or install a bundle by hand with `./deployBotBundle.sh`. + `/srv/bot/app` is created empty by `install.sh`; the container idles until a release lands there. - Discord developer portal: application, redirect URIs, bot; DNS records A `.env`-driven Authentik blueprint would remove the first line (planned). @@ -575,6 +580,8 @@ A `.env`-driven Authentik blueprint would remove the first line (planned). /srv/media/clips//.stlocal Syncthing ignore list maintained by the sweep /srv/media/clips//.src/clip.mkv raw source, only for clips that did NOT arrive via Syncthing /srv/media/clips//clip.normalize-failed.log only if normalization failed; delete to retry + /srv/bot/app/ the Discord bot's installed release (bind-mounted at /app) + /srv/bot/previous/ the release before it (deployBotBundle.sh --rollback) /srv/media/finals/ editors upload here /srv/media/trash//... dumped, purged after 3 days /srv/media/.markers/ dump markers diff --git a/deploy.sh b/deploy.sh index 754523c..ccd2eb5 100755 --- a/deploy.sh +++ b/deploy.sh @@ -49,6 +49,7 @@ apply_changes() { if has '^bin/'; then run install -m 0755 bin/normalize-sweep.sh bin/trash-purge.sh bin/dumpd.py bin/vgstrip.py bin/vgdeband.sh /usr/local/bin/; fi if has '^systemd/'; then run install -m 0644 systemd/*.service systemd/*.timer /etc/systemd/system/; run systemctl daemon-reload; fi if has '^deploy\.sh$'; then run install -m 0755 deploy.sh /usr/local/bin/vanguard-deploy; fi + if has '^deployBotBundle\.sh$'; then run install -m 0755 deployBotBundle.sh /usr/local/bin/vanguard-deploy-bot; fi if has '^firewall/nftables\.conf$'; then run install -m 0644 firewall/nftables.conf /etc/nftables.conf; run nft -f /etc/nftables.conf; fi # 2. regenerate configs (Caddy reload, copyparty restart) — configure.py decides; MediaMTX is handled below diff --git a/install.sh b/install.sh index af9e8e1..faebe3a 100755 --- a/install.sh +++ b/install.sh @@ -41,7 +41,7 @@ install -d -o 1000 -g 1000 /srv/media/{streams,clips,finals,trash,.markers,.sync install -d -o 1000 -g 1000 /srv/appdata/jellyfin/{config,cache} /srv/appdata/authentik/{media,templates,certs} install -d /srv/appdata/authentik/{db,redis} /srv/appdata/mariadb install -d -o 1000 -g 1000 /srv/appdata/discord-bot /srv/appdata/gitea /srv/appdata/act_runner -install -d -o 1000 -g 1000 /srv/bot /srv/bot/app # the Discord bot's deployed CI bundle (bind-mounted at /app) +install -d -o 1000 -g 1000 /srv/bot /srv/bot/app # the Discord bot's released CI bundle (bind-mounted at /app; see bot/README.md) install -d -o "$OWNER" /srv/live # live portal static build (deployLive.sh) install -d -o 1000 -g 1000 /srv/media/streams/{techy,diceofire} /srv/media/clips/{techy,diceofire} for d in /srv/media/clips/*/; do @@ -51,6 +51,7 @@ done echo "== host scripts + units" install -m 0755 bin/normalize-sweep.sh bin/trash-purge.sh bin/dumpd.py bin/vgstrip.py bin/vgdeband.sh /usr/local/bin/ +install -m 0755 deployBotBundle.sh /usr/local/bin/vanguard-deploy-bot # dumpd runs this for the bot CI's POST /deploy-bot install -d -m 0750 /etc/vanguard install -m 0640 dump-users.txt /etc/vanguard/dump-users.txt install -m 0644 systemd/*.service systemd/*.timer /etc/systemd/system/