The vault was 155 pages / 31,210 lines, most of it measurement ledgers for payloads that no longer run. A throughput figure for a runtime nobody operates is not a record: AI moves faster than the vault, so the number is wrong before anyone reads it, and a wrong number in a runbook gets believed. Per the new purpose test in `AGENTS.md` → *Documentation Policy*, it is destroyed. Gone (`.AGENTTRASH/20261019-destruction/`, KILL-LIST.txt is the manifest): - the `frank-medium` endpoint and its five era pages, `frank-npu`, FastFlowLM, the ikllama/kingjones/dealign/frank-redo eras, the ling/swift15/freetoken/ubatch campaign pages, qwen3.8 spec-matrix and strix-optimizations, the two "Running Qwen3.6 …" pages; - the whole `Pipeline Parallelism/` folder (no live script passes a pipeline flag) and the multi-device/x4-pair/hybrid/offload experiment pages; - every vLLM page — no vLLM endpoint exists on this fleet; - `LLM/deployment.md` (`Architecture/Deployment Flow.md` is the test-referenced owner) and the external surveys (SGLang, Lemonade, llama.cpp forks/diff, self-hosted app census, the TTS survey) that were obsolete by construction; - `log.md`, 2,380 lines. Git holds the chronology; a causal law belongs to the page that owns the thing it governs, never to a diary. Survivors: 101 pages, 17,542 lines, 0 OKF violations, 0 unresolved links. Eras tables keep the window, payload, runtime, reason and rollback pointer; the rate columns are blanked. The live shapes stay verbatim — those numbers are what the deployer and `models.yml` consume.
133 lines
7.0 KiB
Markdown
133 lines
7.0 KiB
Markdown
---
|
|
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/<svc>/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) — ACTIVE
|
|
|
|
qBittorrent downloads through gluetun (netns share); the arrs run without it.
|
|
Provisioned 2026-09-01 with a **second Proton WireGuard config** (server
|
|
`PA-12`; the downloaded `.conf` lives in `~/Downloads/FrankBook-Pro-PA-12.conf`
|
|
on Dankware). One config = one keypair — reusing Dankclaw's would bounce the
|
|
server-side endpoint and kill SearXNG. The Seattle server the plan originally
|
|
assumed is equally valid; only endpoint + server pubkey must match the
|
|
chosen config. Egress verified from inside the VM: `curl ifconfig.me` shows
|
|
the Proton PA exit (never the residential IP), ~19 MB/s sustained on a live
|
|
torrent.
|
|
|
|
`/home/core/Containers/gluetun/env` (0600, inside the VM):
|
|
|
|
VPN_SERVICE_PROVIDER=custom
|
|
VPN_TYPE=wireguard
|
|
WIREGUARD_PRIVATE_KEY=<from the Proton .conf>
|
|
WIREGUARD_ADDRESSES=<from the Proton .conf>
|
|
WIREGUARD_PUBLIC_KEY=<that server's pubkey>
|
|
WIREGUARD_ENDPOINT_IP=51.179.177.2
|
|
WIREGUARD_ENDPOINT_PORT=51820
|
|
WIREGUARD_ALLOWED_IPS=0.0.0.0/0,::/0
|
|
WIREGUARD_PERSISTENT_KEEPALIVE_INTERVAL=25s
|
|
|
|
The private key is hashed into the VM env file and never enters the repo.
|
|
NAT-PMP inbound forwarding is available on Proton (gluetun supports it
|
|
`FIREWALL_INPUT_PORTS` + `NATPMP=true`) — deliberately deferred: the e2e
|
|
gate passes outbound-only, and swarm peers needing an inbound port is a
|
|
seeding-era concern, not a grab-only one.
|
|
|
|
## Deploy flow
|
|
|
|
Same deployer as every host: `./scripts/deploy.sh frankbook-pro --service
|
|
<svc>` 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) and the qB
|
|
WebUI (8080). The two **6881 tcp+udp agents were retired**: gvproxy binds a
|
|
wildcard `*:6881/udp` listener (dual-stack; Go sets `SO_REUSEADDR` on TCP but
|
|
not UDP), so the socat-specific bind collides at every boot — delete the
|
|
agents; swarm inbound (if ever needed) is the Proton NAT-PMP path, not the
|
|
LAN one. Note macOS's application firewall still filters gvproxy inbound
|
|
from non-local sources (stealth mode drops unsolicited packets), so
|
|
cross-host reachability of 8080 from other LAN boxes may need
|
|
`socketfilterfw` allowlisting of gvproxy — Mac-local use and swarm egress
|
|
are unaffected.
|
|
|
|
## qBittorrent runtime + wiring (2026-09-01)
|
|
|
|
- `WebUI\Password_PBKDF2` 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 the arr wiring. The first seed wrote the hash
|
|
under the legacy `WebUI\Password` key (silently ignored → every client
|
|
got `Unauthenticated`); the live conf was patched and
|
|
`scripts/deploy-remote.sh` fixed to write the `_PBKDF2` key. Gotcha
|
|
(live, 2026-09-01): after qB 5.x ran, its conf rewrite left a hash line
|
|
4.6.7 rejects (`invalid credentials` for every login, including the arrs)
|
|
rewriting the same `@ByteArray` line fresh (same password, 100k
|
|
iterations) restored login. Any future version flip: regenerate the line.
|
|
- `HostHeaderValidation=false` + `ServerDomains=*`: the socat forwarder
|
|
preserves the LAN `Host` header, which would otherwise be rejected.
|
|
- **Save-path convention**: `Session\DefaultSavePath=/Volumes/COMPLETE/
|
|
Finished Torrents`, `Session\TempPath=/Volumes/INCOMPLETE/incomplete`
|
|
(two-disk layout: partials on INCOMPLETE, qB moves on completion).
|
|
qB 5.2 API adds with a category do **not** inherit the category save
|
|
path (no auto-TMM), so the default itself points at `Finished Torrents`:
|
|
every grab lands there regardless of client behavior; human review moves
|
|
files onward; nothing writes to the entropy volume.
|
|
- Categories seeded: `Finished Torrents`, `lidarr`, `radarr`, `readarr`
|
|
`tv-sonarr` (all → `Finished Torrents`).
|
|
- **Download clients** (gateway `10.88.0.1:8080`, user `admin`): all five test
|
|
green against live qB — sonarr (`tv-sonarr`), radarr, lidarr, readarr
|
|
(rows pre-created in the prior session; passwords re-pushed via API), and
|
|
prowlarr (created from the `/downloadclient/schema` template — a
|
|
hand-minimal body 400s in Prowlarr's create-time test). Readarr's EOL
|
|
validator (last release 2023) rejects qB ≥ 5's `204` empty login success
|
|
as "Authentication failure" — that kills runtime auth too, not just API
|
|
creates; the fix was pinning qB itself (below), after which readarr tests
|
|
200 like the rest.
|
|
- **qB pinned to 4.6.7** (`Image=lscr.io/linuxserver/qbittorrent:4.6.7`
|
|
not `latest`): `latest` resolved to 5.x, whose `204` login breaks
|
|
Readarr's frozen client; 4.6.7 answers the legacy `200` + `"Ok."` that
|
|
every client accepts. Pinned in
|
|
`frankbook-pro/qbittorrent/quadlet/qbittorrent.container`.
|
|
- **Prowlarr Applications** push to sonarr/radarr/lidarr (`fullSync`
|
|
gateway ports). Readarr deliberately omitted: prowlarr's indexer-push
|
|
test to readarr's `/api/v1/indexer/test` 500s (EOL schema drift).
|
|
Legacy `Prowlarr-*` indexer rows carried in the migrated dankserver DBs
|
|
pointed at the unresolvable hostname `prowlarr:9696` and were deleted;
|
|
the current `*(Prowlarr)` entries test OK.
|
|
- **E2E proven (2026-09-01, on 4.6.7)**: added a legal test torrent via the
|
|
API with category `Finished Torrents` — downloaded through the tunnel
|
|
(~17 MB/s), qB moved it INCOMPLETE → COMPLETE into
|
|
`/Volumes/COMPLETE/Finished Torrents`, then deleted with data.
|
|
|
|
# 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`
|