# Deployment, per-rig state, secrets, sandbox

**Read when:** bringing up a fresh rig (Midgolem or otherwise), rotating tokens, deciding what to commit vs regenerate, or hitting Flatpak sandbox / hardcoded-asset issues.

## Deploy a fresh rig

```bash
git clone <repo> ~/.config/obs-studio
cd ~/.config/obs-studio
bash scripts/deploy-rig.sh
```

Idempotent. 9 phases: pacman + pip + flatpak + submodules + PipeWire sink + MPD + systemd units + OBS first-launch + secrets stub. See file header for details.

## Twitch identity & secrets

| Account | Purpose | Token file | Scopes |
|---|---|---|---|
| `ophi118` (broadcaster) | Channel title/category updates by `set-channel.py` | `twitch-bot/.env.ophi118` | `channel:manage:broadcast` |
| `vault118` (bot) | Handles `!skip` / `!queue` / `!info`, posts now-playing, optional Mattermost going-live notifier (outbound HTTP only — no extra Twitch scopes needed) | `twitch-bot/.env` | `chat:read`, `chat:edit` |
| `ophi118` (stream key) | RTMP stream key | `basic/profiles/ophi118/service.json` | n/a |

All three are gitignored. **Do not copy between rigs** — regenerate via https://twitchtokengenerator.com (for OAuth tokens) and the Twitch Dashboard (for the stream key).

## External assets referenced by absolute path

These hardcoded paths exist in `basic/scenes/Default_Stream_HUD.json`. On a fresh rig they need to exist or OBS will surface "missing source" errors:

| Path | Purpose |
|---|---|
| `/home/jin/HDD/Images/Gifs/stamd.png` | Game-scene "Starting Soon" image |
| `/home/jin/cloud.jakubzych.com/_img/logos/dgw.png` | Doomguard watermark (Game/Landing) |
| `/home/jin/HDD/Music/` | MPD library root |
| `/home/jin/Videos/` | Recording output |
| `/home/jin/.config/obs-studio/landing/static-hum.wav` | Landing audio |

`scripts/deploy-rig.sh` creates the directories and warns about missing image files; the user has to bring those over manually.

## Per-rig vs portable state

**Differs per rig** (don't copy from one to the other; let the deploy script or OBS itself regenerate):
- `global.ini` — ALSA device IDs, monitor IDs
- `~/.config/mpd/mpd.conf` — `zeroconf_name`
- `twitch-bot/.env*` — OAuth tokens
- `basic/profiles/ophi118/service.json` — stream key
- `plugin_config/obs-websocket/config.json` — WebSocket password
- `landing/telemetry.json` — `rig`, hardware specs, kernel
- `vendor/obs-config.js` — derived from WS password

**Identical across rigs** (commit and reuse):
- `basic/scenes/Default_Stream_HUD.json` — scenes + transitions + audio routing
- `basic/profiles/ophi118/{basic,streamEncoder,recordEncoder}.json` — encoder/output settings (minus `service.json`)
- All HTML overlays under `landing/`, `loading/`, `game/`, `desktop/`, `goodbye/`, `music-box/`, `music/`
- All Python in `bridges/`, `twitch-bot/`
- All scripts in `scripts/`
- `vendor/obs-ws-mini.js`

**Outside this repo but written by `scripts/deploy-rig.sh` (identical across rigs):**
- `~/.config/pipewire/pipewire-pulse.conf.d/mpd-stream.conf` — MPD null sink + loopback
- `~/.config/pipewire/pipewire-pulse.conf.d/discord-stream.conf` — Discord null sink + loopback

**Manual one-time per rig (no automation):**
- pavucontrol → Playback → Discord → set output to **Discord-Stream** (PipeWire remembers across launches; Discord has no equivalent of MPD's `target` config).

## Flatpak permissions — what the sandbox allows

OBS flatpak ships with `filesystems=host` by default — full host access. Asset paths under `/home/jin/HDD/`, `/home/jin/cloud.jakubzych.com/`, etc. work without `flatpak override`. PipeWire audio works via `xdg-run/pipewire-0`. NVIDIA acceleration works via `org.freedesktop.Platform.GL.nvidia-*` (auto-installed). If you ever need to widen permissions: `flatpak override --user com.obsproject.Studio --<flag>=<value>`.

`filesystems=host` is also the reason this config lives at `~/.config/obs-studio/` instead of the per-app sandboxed path — see CLAUDE.md "What this directory is".
