Add a Podman Quadlet cookbook for Home Assistant.
- Runs as the non-root home-assistant user (UID 10034, GID itix-svc/10000);
s6-overlay v3 self-adjusts /run so no root or idmap workaround is needed.
- PostgreSQL recorder backend (postgresql hook) with the connection string kept
out of packaged files via !secret; Traefik ingress (traefik hook) with the
X-Forwarded-For / trusted_proxies settings a reverse-proxied HA requires.
- /config is precious data on the virtiofs mount; a one-shot init unit bootstraps
configuration.yaml and secrets.yaml into it only when absent (never overwriting
the live copy Home Assistant owns) and creates the empty automations/scenes/
scripts include targets so a fresh /config does not fall into recovery mode.
- Weekly native backup automation writing into /config/backups.
- Health check on /manifest.json with cold-start-sized timeouts.
Verified on a clean Fedora CoreOS VM (real virtiofs): home-assistant.target
active, 8123 answering, recorder writing 13 tables into PostgreSQL, all
containers healthy, and a re-run of the init unit leaving the live config intact.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Runs a browser on the seedbox and displays it on the workstation through
waypipe, for the cases FlareSolverr cannot cover: logging into a private
tracker, or reaching an interface only exposed on the seedbox network.
waypipe lives in the container rather than on the Fedora CoreOS host. The
waypipe server has to share a mount namespace with the browser, and putting it
in the image keeps the host a stock, unlayered CoreOS while pinning the waypipe
version -- 0.9 (C) and 0.10+ (Rust) do not interoperate. The entry point is
seedbox-waypipe.sh, passed to the client with --remote-bin, because
"ssh <host> <command>" never sources /etc/profile.d.
LibreWolf because the seedbox is aarch64, which rules out Tor Browser and
Mullvad Browser (no Linux arm64 build). It ships resistFingerprinting, uBlock
Origin and no telemetry out of the box, and disables its own updater, which
suits an image rebuilt nightly by librewolf-build.timer.
Four things that are not obvious from the code:
- SELinux checks "connectto" on a Unix socket against the listening process,
not the socket file, and the listener is the unconfined SSH session. No
label the container could carry is allowed to connect, hence
--security-opt label=disable rather than a system-wide policy module.
- Firefox's content sandbox chroots itself and needs CAP_SYS_CHROOT in the
bounding set, while bubblewrap -- used by the SVG image loader -- refuses to
run when the caller holds capabilities without being setuid. podman puts
--cap-add in the ambient set too, so the image entrypoint drops ambient and
inheritable capabilities with setpriv, leaving the bounding set alone.
- The forwarded socket is bind-mounted by directory, not by file: mounting the
file alone makes podman synthesize a root-owned 0755 parent inside the
container, and waypipe then cannot unlink its own socket on shutdown.
- "waypipe ssh" forwards several of its own options to the server side, and a
repeated flag is a hard error, so the shim only injects what is absent.
The browser deliberately does not use Network=host, unlike the rest of the
stack: a hostile page must not reach the *arr interfaces on localhost.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017kXTkLKMkwYSHZET7ckzmd