Add a `mosquitto` cookbook running Eclipse Mosquitto 2 (multi-arch
docker.io/library/eclipse-mosquitto:2) as a rootless, non-root container
(UID 10033 / GID 10000) serving as the MQTT backbone of a home-automation
stack.
Design highlights:
- Plain MQTT on 127.0.0.1:1883 only; TLS is terminated at Traefik (:443,
SNI-routed) via a TCP router hook fragment (other/traefik/mosquitto.yaml).
Depends on the traefik cookbook.
- Anonymous access refused; password_file and acl_file are operator-provided
(working examples shipped under config/examples/, installed 0640 10033:10000).
No credential is baked into a packaged file.
- Retained messages and sessions persist to the virtiofs precious-data mount
(/var/lib/virtiofs/data/mosquitto), purged on uninstall via a tmpfiles `d$`
entry.
- log_dest stdout so journalctl is the single place to look.
- include_dir conf.d shipped as an empty packaged directory (mosquitto fails if
it is missing); hooks.mk lets dependent cookbooks drop conf.d fragments.
- Health check is an unauthenticated `nc -z 127.0.0.1 1883` TCP connect, so it
needs no secret that may not exist yet.
Verified: make dryrun, whole-repo `make package`, and a podman-level functional
run (non-root startup, loopback-only bind, anonymous refused, authenticated
pub/sub round trip, retained message surviving a restart, health probe).
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