# PeerTube Setup — Tactical Media Broadcast Hub's video/live backbone PeerTube runs as a **subproject** (`infra/peertube/`) on a **different server** than the Tactical Media Broadcast Hub API/web. It stores all media in **S3** and carries the **Tactical Media Broadcast Hub brand**, propagated from this repo. ## Deploy (on the media server) 1. `cp infra/peertube/.env.example infra/peertube/.env` — fill in hostname, S3 keys (dedicated buckets: `tactical-media-broadcast-hub-peertube-{videos,playlists,redundancy}`), DB password 2. `docker compose -f infra/peertube/docker-compose.yml up -d` 3. Put the instance behind HTTPS (nginx/caddy) — federation + OAuth require it 4. First boot creates the admin account (PEERTUBE_ADMIN_EMAIL) ## S3 storage PeerTube's object-storage env handles ALL media (videos, playlists, redundancy). Point it at the same S3-compatible infra the Tactical Media Broadcast Hub media plane uses (MinIO or cloud), with dedicated buckets + credentials. The Tactical Media Broadcast Hub API never proxies PeerTube bytes — both speak S3 natively. ## Branding — propagation rule **Source of truth: this repo** (`apps/web/public/brand/` + design tokens in `apps/web/src/app/globals.css`). After ANY brand change: ``` infra/peertube/brand-sync/sync-brand.sh ``` It pushes instance name, custom CSS (accent #FF1610 on black), and the solid disk mark to the instance via PeerTube's config API (needs `PEERTUBE_URL` + `PEERTUBE_TOKEN` with settings scope). Idempotent — run it whenever the brand moves. (Later: a "Sync branding" button in Tactical Media Broadcast Hub settings that calls the same API.) ## Connecting Tactical Media Broadcast Hub → PeerTube - **OAuth bridge**: stock PeerTube exposes a password grant only. Our connect flow (docs/oauth-connect.md) supports a same-instance OAuth bridge when configured; otherwise use an instance with a bridge plugin or a token-entry connection. The connector (`packages/connector-peertube`) handles publish, livestream keys, per-instance federation. - **Live ingest**: the media worker's compositor pushes RTMP to `:1935` (opened in the compose file). Livestream keys flow through the connector. - **Live chat**: install the **livechat plugin** (peertube-plugin-livechat) on the instance — S5's chat hub consumes chat via the XMPP/plugin surface (phase 2 of S5, per the streaming architecture doc). ## Different-server topology ``` [app server] [media server] apps/api apps/web scheduler peertube (+redis +postfix) media-worker compose (pg, S3 buckets (dedicated peertube-*) redis, temporal...) │ └────── RTMP :1935 ───────┘ └────── OAuth/API over HTTPS ──┘ ``` Firewall: app server → media server :443 (API) and :1935 (RTMP). Nothing else required between them; S3 is the shared storage plane. ## Settings checklist (instance admin UI, after first boot) - Enable live + allow replay + transcode lives - Registration: closed (users join via Tactical Media Broadcast Hub) - Federation: follow only trusted instances (moderated homepage) - Plugins: peertube-plugin-livechat (chat), optionally peertube-plugin-rtc