Files
serverAppConfigs/serverAppConfigs-docs/Infrastructure/FrankBook-Pro.md
T

102 lines
4.8 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)
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.
### Prepared Mac peer (2026-09-01 — waiting on server-side add)
A dedicated keypair is generated and parked on Dankclaw
(`~/frankbook-wg/mac-private.key`, 0600, host-local — never in the repo).
Lighting the tunnel needs exactly one change on the WireGuard server
(149.102.254.77): register a new peer for the Mac — different keypair from
Dankclaw's (one key cannot serve two machines; the server bounces the
endpoint between them), same endpoint and server key:
- Server pubkey (route target): `utqNH4P+C0fA1wTgIUaIfhm1b7ai0iEGvXyiw4KC3Fs=`
- Endpoint: `149.102.254.77:51820` (`VPN_SERVICE_PROVIDER=custom`)
- Mac public key to register as the new peer:
`QIoCwI+9VuiWldRvUfPpTfXq7UVVBFynIqYb2vqHtQo=`
- Allocate the Mac a fresh tunnel IP as the peer's allowed IP — Dankclaw
holds `10.2.0.2/32`, so likely `10.2.0.3/32` unless the server numbers
differently.
Then `/home/core/Containers/gluetun/env` (0600) inside the VM:
VPN_SERVICE_PROVIDER=custom
VPN_TYPE=wireguard
WIREGUARD_PRIVATE_KEY=<raw b64 private key — fetch from dankclaw:~/frankbook-wg/mac-private.key>
WIREGUARD_ADDRESSES=<allocated tunnel IP>/32
WIREGUARD_PUBLIC_KEY=utqNH4P+C0fA1wTgIUaIfhm1b7ai0iEGvXyiw4KC3Fs=
WIREGUARD_ENDPOINT_IP=149.102.254.77
WIREGUARD_ENDPOINT_PORT=51820
WIREGUARD_ALLOWED_IPS=0.0.0.0/0,::/0
WIREGUARD_PERSISTENT_KEEPALIVE_INTERVAL=25s
Deploy with `./scripts/deploy.sh frankbook-pro --service gluetun --service
qbittorrent`, then verify egress from the VM (`podman exec gluetun curl -s
ifconfig.me` must NOT show the residential IP) before declaring the
BitTorrent port usable.
## 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), 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`