Files
Media-Server-Setup/FRESH-INSTALL.md

124 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Fresh install — from an empty OVH box to a working stack with the deploy pipeline
Everything in order. Scripted steps are commands; manual steps are click lists. `HOST` = your main hostname
(ours: `ovh1.dumpstervigilantes.rip`), `BASE` = the parent domain. Detailed background for each part is in
README.md (section numbers given).
## 0. Before touching the server
- DNS: `A` record for `HOST` → the server IP; `CNAME`s `auth`, `watch`, `git`, `bot`, `live` → `HOST`.
Optional: the bare domain `A` → server IP (it redirects to the watch site or `/about/`).
- 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
source slug — keep them identical). Copy Client ID + Client Secret.
- Bot → Reset Token (copy it); enable **Server Members** intent; OAuth2 URL generator: scope `bot`, permissions
View Channels + Send Messages + Embed Links + Attach Files → invite it to the server.
- Discord → User Settings → Advanced → Developer Mode on; right-click the server → Copy Server ID; Server
Settings → Roles → Copy Role ID for each role you will map to a group.
- If this is a **rebuild**, have the backups ready: `.env`, `/srv/appdata`, `/srv/media`, `/etc/vanguard/clip-quotas.json`.
Restoring `.env` + `/srv/appdata` makes sections 5–7 unnecessary (that state lives there).
## 1. OS (README §1)
OVH manager → Reinstall → Debian 13, custom partitioning, distribution kernel. RAID 1:
`/boot` 1 GB ext4 · `/` 250 GB ext4 · swap 8 GB per disk · `/srv` rest xfs. Add your SSH key. You get the `debian` user with sudo.
## 2. Code onto the box
Fresh box has no deploy key yet, so copy the repo in:
scp -r vanguard-stream debian@HOST:~/ # from a machine that has the repo (or git clone over https with a token)
## 3. Host install (README §2, §4)
ssh debian@HOST
cd ~/vanguard-stream && sudo bash install.sh
Packages, Docker, timezone (Eastern), uid 1000, `/srv` folders, host scripts and timers, sysctl, live-portal
build, **firewall** (keep this session open; test a new ssh in a second terminal). Log out and back in once (docker group).
## 4. Configure + start (README §3)
cd ~/vanguard-stream && ./configure.py --full
Asks: main hostname; `auth`/`watch`/`git`/`bot`/`live` hostnames (defaults); bare domain (optional) and where it
redirects; Discord bot token + server ID (optional now, needed for the plugin feed); "is live" webhook (optional).
Generates `.env` with every secret, the configs, starts all containers, waits, then runs the post-start fixups
(Syncthing GUI auth off, Gitea admin user, Jellyfin plugin). `./configure.py --show` prints every credential
you will need below (akadmin password, Gitea admin, MariaDB, bot DB).
Check: `docker compose ps` → all `Up`; `https://auth.BASE/`, `https://watch.BASE/`, `https://git.BASE/`,
`https://HOST/` answer with certificates (Caddy fetches them itself, give it a minute).
## 5. Authentik (README §5c, §5g) — manual, ~20 minutes
Log in at `https://auth.BASE/` as `akadmin` with `AUTHENTIK_BOOTSTRAP_PASSWORD` from `.env` (change it: user menu → settings).
1. Directory → Federation & Social login → Create → **Discord OAuth Source**: name `Discord`, slug `discord`,
consumer key/secret = the Discord app's Client ID/Secret, scopes `guilds guilds.members.read`, user matching
"link on unique identifier", flows default-source-authentication / default-source-enrollment.
2. Flows & Stages → Stages → `default-authentication-identification` → Sources: add Discord, tick "Show sources'
labels". (No Discord button appears until this is done.)
3. Flows & Stages → Stages → `default-source-enrollment-write` → User type **Internal**, user path `users`.
4. Directory → Groups: `streamers`, `editors`, `media-admins`, `admins`, `bot-users`, `git-users`, `git-admins`.
Nesting: `admins` parent `authentik Admins`; `authentik Admins` parent `git-admins` (admins inherit everything).
5. Customization → Policies → Create Expression Policy ×2 from the repo:
`discord-guild-member` (`authentik/discord-guild-policy.py`, set your server ID) and
`discord-roles-to-groups` (`authentik/discord-roles-to-groups.py`, set server ID + role-id→group table).
Tick "Execution logging" on both.
6. Flows & Stages → Flows → `default-source-enrollment` and `default-source-authentication`: bind both policies
(guild first), **Policy engine mode: all**.
7. Applications → Outposts → edit "authentik Embedded Outpost" → config `authentik_host: https://auth.BASE`.
8. Applications → Create with provider → `Vanguard sites`: **Proxy Provider**, implicit consent,
**Forward auth (domain level)**, authentication URL `https://auth.BASE`, cookie domain `BASE`,
invalidation flow `default-provider-invalidation-flow`. Edit the Embedded Outpost → add the application.
9. Applications → Create with provider → `Jellyfin`: OAuth2/OpenID, implicit consent, Confidential, redirect
`https://watch.BASE/sso/OID/redirect/authentik`, default signing cert, scopes `openid email profile`. Keep ID + secret.
10. Applications → Create with provider → `Gitea` (slug `gitea`): OAuth2/OpenID, same settings, redirect
`https://git.BASE/user/oauth2/authentik/callback`. Bind groups `git-users` + `git-admins` on the application.
11. Test in a private window: `https://auth.BASE/` → Discord → your user exists and is Internal. Add yourself to
`admins` (and `streamers`, `media-admins` as needed) or give yourself the Discord roles; sign out and back in.
`https://HOST/whoami` shows your groups.
## 6. Jellyfin (README §5c) — manual, ~10 minutes
`https://watch.BASE/` → wizard: admin user; libraries `/media/streams` and `/media/clips` as **Shows** with
metadata downloaders = only "Vanguard Metadata" (Series/Season/Episode), image fetchers Vanguard Metadata
(Series) + Screen Grabber (Episode), real-time monitoring on; `/media/finals` as Home Videos, fetchers off.
Dashboard → Playback → Transcoding: hardware acceleration none. Dashboard → Plugins: Vanguard Metadata is
installed → its page: Discord bot token + server ID, feed channel ID, public URL `https://watch.BASE`.
Plugins → Repositories → add `https://raw.githubusercontent.com/9p4/jellyfin-plugin-sso/manifest-release/manifest.json`
→ Catalog → SSO Authentication → install → `docker compose restart jellyfin`. Plugins → SSO-Auth → add OID provider
`authentik`: endpoint `https://auth.BASE/application/o/jellyfin/`, client ID/secret, roles claim `groups`,
admin roles `admins`, enabled folders = the 3 libraries, Scheme Override `https`, Port Override EMPTY, Save.
Dashboard → General → Branding: paste `jellyfin/branding-disclaimer.html` (set the hostname) and `jellyfin/branding.css`.
Test: `https://watch.BASE/sso/OID/start/authentik`. Scheduled Tasks → run "Vanguard: snapshot Discord events",
"roll seasons", "enforce playback policy" once.
## 7. Gitea (README §5e) — manual, ~10 minutes
Log in at `https://git.BASE/` as `GITEA_ADMIN_USER` / `GITEA_ADMIN_PASSWORD` from `.env`.
1. Site Administration → Identity & Access → Authentication Sources → Add: OAuth2, name `authentik`, OpenID
Connect, client ID/secret from step 5.10, discovery URL
`https://auth.BASE/application/o/gitea/.well-known/openid-configuration`, Skip local 2FA, group claim
`groups`, administrator group `git-admins`.
2. Create the repo `techy/Media-Server-Setup` (empty) and push this repo to it from your dev box:
`git remote add origin ssh://git@git.BASE:2222/techy/Media-Server-Setup.git && git push -u origin main`
(your SSH key under Settings → SSH keys).
3. Runner: `./registerGiteaRunner.sh` on the server → Site Administration → Actions → Runners shows it idle.
## 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`.
2. Gitea → repo → Settings → Webhooks → Add → Gitea: URL `http://<docker gateway>:8081/deploy`
(`docker network inspect vanguard-stream_default -f '{{(index .IPAM.Config 0).Gateway}}'`), secret =
`DEPLOY_WEBHOOK_SECRET` from `.env`, push events, branch `main`. Test delivery → 202 "auto-deploy disabled".
3. Manual deploys from now on: push, then `sudo vanguard-deploy pull` on the server. When trusted:
`DEPLOY_AUTO=1` in `.env` → `./configure.py --apply`; CI: `git mv .gitea/draft-workflows/ci.yml .gitea/workflows/ci.yml`.
## 9. Streamers, gamers, editors (README §5, §5a, §6)
- Streamers: OBS → WebSocket server on; Docks → Custom Browser Dock `https://HOST/dock/` → Discord login →
Settings: OBS WebSocket password; Timecode band → "Add band + clock source" (not streaming). Then title → Go Live.
- Gamers: `https://HOST/clips/` → paste their Syncthing Device ID → accept device + folder on their PC (Send Only).
Syncthing UI (`https://HOST/sync/`, media-admins): Actions → Settings → Connections → incoming rate limit 12500 KiB/s.
- Everyone: `https://HOST/about/`.
## 10. Afterwards
- Pin `AUTHENTIK_TAG` in `.env` to the running version. Rotate any secret that was ever pasted into chat.
- Back up `.env`, `/srv/appdata`, `/srv/media` (home archive puller: README §7).
- `STATUS.md` = what runs and what is unfinished; `check.sh` before any commit.