From b6be6d3da6ab0d8ab2bc936442612fc2b5813f64 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 1 Sep 2026 14:32:57 -0700 Subject: [PATCH] docs: FrankBook-Pro page + 2026-09-01 log Document the Mac *arr/qBittorrent stack (VM placement, gluetun credential gate, socat LaunchAgents, PBKDF2 qB seed) and log the day: dankserver recovery + full quadlet cutover of the six media services, the frankbook skip-propagation/PBKDF2 handler fix, the 7-service frankbook deploy, and the jellyfin GPU-parity finding. --- .../Infrastructure/FrankBook-Pro.md | 67 +++++++++++++++++++ serverAppConfigs-docs/index.md | 1 + serverAppConfigs-docs/log.md | 7 ++ 3 files changed, 75 insertions(+) create mode 100644 serverAppConfigs-docs/Infrastructure/FrankBook-Pro.md diff --git a/serverAppConfigs-docs/Infrastructure/FrankBook-Pro.md b/serverAppConfigs-docs/Infrastructure/FrankBook-Pro.md new file mode 100644 index 0000000..41f7c7a --- /dev/null +++ b/serverAppConfigs-docs/Infrastructure/FrankBook-Pro.md @@ -0,0 +1,67 @@ +--- +type: reference +description: FrankBook-Pro — the Mac mini running the *arr stack + qBittorrent inside a podman machine VM, gluetun-gated +tags: [frankbook-pro, mac, arr, qbittorrent, gluetun, wireguard, podman-machine] +timestamp: 2026-09-01 +--- + +# FrankBook-Pro + +FrankBook-Pro (192.168.0.112, macOS x86_64, Intel) runs the *arr automation +stack and qBittorrent inside a **podman machine** VM (Fedora CoreOS-style +`core` user). Seven quadlet units live in `frankbook-pro//quadlet/`: +`gluetun`, `qbittorrent`, `prowlarr`, `sonarr`, `radarr`, `lidarr`, `readarr`. + +## Why a VM, and why inside it + +- macOS podman runs containers inside a VM; quadlet units are installed in the + VM (`/home/core/.config/containers/systemd/`) via `podman machine ssh`. +- `/Volumes/COMPLETE` (review disk) and `/Volumes/INCOMPLETE` (in-progress + disk) are virtiofs-mounted into the VM, so qBittorrent writes straight to + the same disks the human review workflow uses. +- Grab-only stack: the arrs never auto-import; nothing writes to the entropy + volume. Completed files land in `/Volumes/COMPLETE/Finished Torrents`. + +## WireGuard gate (gluetun) + +qBittorrent downloads through gluetun (netns share); the arrs run without it. +Until `/home/core/Containers/gluetun/env` contains the WireGuard credentials +(a second peer for the Mac — reusing Dankclaw's key would flip its tunnel and +kill SearXNG), `deploy_frankbook_stack` **skips** gluetun and qbittorrent +with instructions and deploys the five arrs anyway. The qB WebUI port stays +unpublished by design; the e2e torrent test waits on the credentials. + +## Deploy flow + +Same deployer as every host: `./scripts/deploy.sh frankbook-pro --service +` from Dankware. The Mac-side handler (`deploy_frankbook_stack` in +`scripts/deploy-remote.sh`) pipes unit files + a seed script through +`podman machine ssh bash -s`, seeds qBittorrent's first-boot config once +(marker file `qbit-seeded`), restarts the selected unit inside the VM, and +health-checks its published port on Mac loopback. + +## LAN reachability + +gvproxy forwards published ports to Mac loopback only. LaunchAgents +(`local.fwd.*` in `~/Library/LaunchAgents`) run socat forwarders binding the +LAN IP (192.168.0.112) for arr UIs (9696/8989/7878/8686/8787), the qB WebUI +(8080, inert until the tunnel is up), and the BitTorrent port 6881 tcp+udp. + +## qBittorrent seed (first boot, inside the VM) + +- `WebUI\Password` is a **PBKDF2** `@ByteArray(salt:hash)` + (PBKDF2-HMAC-SHA512, 100k iterations, 64 bytes) — qB ≥ 4.2 ignores + plaintext. The plaintext lives in `/home/core/Containers/qbittorrent/env` + (mode 600, VM-local) for Prowlarr wiring. +- `HostHeaderValidation=false` + `ServerDomains=*`: the socat forwarder + preserves the LAN `Host` header, which would otherwise be rejected. +- `categories.json` pre-creates `Finished Torrents`, `lidarr`, `radarr`, + `tv-sonarr` with save_path `/Volumes/COMPLETE/Finished Torrents`. +- `Session\DefaultSavePath=/Volumes/COMPLETE`, + `Session\TempPath=/Volumes/INCOMPLETE/incomplete` (two-disk layout). + +# Citations + +- Plan: `local://podman-standardization-arr-migration-plan.md` (session 2026-09-01) +- Units: `frankbook-pro/*/quadlet/*.container`, seam `tests/frankbook_quadlet.bats` +- Handler: `deploy_frankbook_stack`, `scripts/deploy-remote.sh` diff --git a/serverAppConfigs-docs/index.md b/serverAppConfigs-docs/index.md index 6c1811b..98a42f6 100644 --- a/serverAppConfigs-docs/index.md +++ b/serverAppConfigs-docs/index.md @@ -86,6 +86,7 @@ covers both workloads). - [[Node-Exporter]] — host metrics - [[Loki]] — log storage - [[Alloy]] — log shipping (replaces Promtail) +- [[FrankBook-Pro]] — Mac mini *arr + qBittorrent inside podman machine (gluetun-gated) ## Research diff --git a/serverAppConfigs-docs/log.md b/serverAppConfigs-docs/log.md index bd3928d..036877e 100644 --- a/serverAppConfigs-docs/log.md +++ b/serverAppConfigs-docs/log.md @@ -214,3 +214,10 @@ timestamp: 2026-09-14 - `/scripts/deploy-remote.sh` — `deploy_caddy` installs/starts the quadlet (retiring the bare container; all state is in host volumes). Boot persistence comes from podman's quadlet generator, which creates the `default.target.wants` symlink from the unit's `[Install]` section at every user-manager start — `is-enabled` reports `generated` for all healthy quadlets, and an explicit `systemctl enable` fails on generated units (learned live during the deploy). `deploy_pihole` enforces the sysctl prerequisites. - `/tests/caddy_quadlet.bats` (new seam), `/tests/caddyfile.bats`, `/tests/deployment_flow.bats`, `/tests/pihole.bats` — quadlet boot-persistence, self-healing, network, env, and sysctl coverage; compose assertions repointed from the removed caddy service to the quadlet. - `/docs/Infrastructure/Caddy.md`, `/docs/Infrastructure/Pi-hole.md`, `/docs/Dankclaw/Dankclaw Stack.md` — quadlet runtime facts, the 2026-08-26 incident, and the sysctl-conflict failure mode. + +## 2026-09-01 +- dankserver SSH recovered after the reboot (the "Not allowed at this time" port-22 responder vanished with it); the media stack had been restarted bare ~35 min post-boot, then the quadlet cutover completed for all six services (romm trio 13:45, jellyfin 13:49, calibre-web 13:50, copyparty 13:53 PDT) — units generated from the repo, data roots migrated to `/home/dank/Containers/`, `/opt/{romm,jellyfin,calibre-web,copyparty}` retired, all four endpoints answering, legacy `container-*` units gone. Dankserver deploy-state for the six services records deployed revisions through `1a257c0`. +- `/scripts/deploy-remote.sh` — frankbook handler fix: the credential-gate SKIP state now propagates Mac-side before restart+verify (a parked qbittorrent previously failed the batch and aborted the five arrs); qB first-boot seed writes a PBKDF2 `@ByteArray` WebUI password (plaintext is ignored by qB ≥ 4.2), sets `HostHeaderValidation=false` + `ServerDomains=*` for the socat forwarder path, and pre-creates the four categories with `save_path=/Volumes/COMPLETE/Finished Torrents`. +- `frankbook-pro` — full 7-service deploy run: gluetun + qbittorrent SKIP cleanly (WireGuard credentials pending — the Mac needs its own peer; reusing Dankclaw's key would flip its tunnel), prowlarr/sonarr/radarr/lidarr/readarr deployed, healthy, and reachable from dankserver over the LAN via the socat LaunchAgents (192.168.0.112). +- jellyfin GPU posture on dankserver: `AddDevice=/dev/dri` + `GroupAdd=keep-groups` in the unit (parity with pre-migration reality — no `/dev/nvidia*` in the container, no working VA-API driver in the image; the old bare container had the same. CPU/direct-play serves the household). +- `/docs/Infrastructure/FrankBook-Pro.md` (new), `/docs/index.md` — documented the Mac stack: VM placement, WireGuard gate, deploy flow, socat LaunchAgents, and the qBittorrent PBKDF2 seed.