menu-admin was the odd one out: it built from the working directory with a date tag and a multi-arch manifest, deployed with `-e tag=`, and kept the Docker-era container name. The other two apps build from `git archive HEAD` and tag with the commit, so what runs on the host is exactly what git knows about; build only for the architecture emily actually runs; and use one slug for the container, its network and its data directory. The build is now their three lines: `podman build --platform linux/arm64` from `git archive HEAD`, tagged `:<commit>` and `:latest`, pushed with `podman push` rather than a manifest. `deploy.sh` pushes the commit first, then refuses a dirty tracked tree or a HEAD that is not origin/main — which is what makes the commit tag trustworthy — takes the same `--force` and `--no-push`, and ends in the same `-u tanshu ... -e image_tag=<commit>`. Its own lint/typecheck/test gate stays, but behind `--checks`, so a plain deploy behaves as theirs does. The registry credential moves into vars/default.yml and the role logs in, pulls and logs out around it, as their roles do. The image is only pulled at deploy time, so the unit keeps podman's default `Pull=missing` and a reboot never needs the registry. This is the same plaintext credential the other two repos carry. One real bug goes with it: the healthcheck gate ran before the handler that restarts a changed unit, so a run that only changed the unit checked the stale container. `meta: flush_handlers` before the gate is the fix the sibling repos already made. The container, network and data directory are all menu-<site> now. The dotted Docker-era name and the NetworkAlias it needed are gone, so `podman logs menu-<site>` and `systemctl --user status menu-<site>` are the same two commands across all three apps. The Dockerfile keeps its name for the same reason: podman reads it as readily as a Containerfile, and the siblings use that name too.
2.3 KiB
Sites run as rootless Podman Quadlets behind a shared Caddy
Each Site is deployed as a rootless Podman container managed by a systemd
user unit (Quadlet) on emily, reached through the one shared Caddy unit rather
than a long-lived rootful Docker container. The image is built by Podman too,
from the committed tree, the same way the sibling hops and greatbear apps are
built and deployed. This matches how every other service on that host is
deployed, and it takes the deployment off Docker entirely.
The app owns its whole serving path, so it needed the smallest deployment of the
fleet: one .container file, one .network file, and a block appended to the
Caddyfile. Two details carry the design. UserNS=keep-id:uid=1000,gid=1000 maps
the image's own node account onto the user that owns the units, which is what
keeps data/ and site.env owned by a real host user — plain tar backups, no
subuids — and scripts/provision-site-env.sh uses the same mapping so both sides
agree on who owns the file. And the Site registers its own network with Caddy by
writing a drop-in beside caddy.container, so Caddy never lists its upstreams
and never has to be edited when a Site is added or removed.
Considered Options: staying on rootful Docker on monoco, rejected because
the fleet is moving and leaving one app behind means two runtimes and two Caddy
configs to reason about; running rootful Podman, rejected because it keeps the
same root-owned data and loses the plain-backup property; and keeping the
Docker-era container name menu-app.<domain>, rejected because a name with dots
in it is a liability in DNS and it would have meant a second name (a network
alias) for Caddy to proxy to. The inventory name is now the single slug for
everything — container, network and data directory are all menu-<site>, so the
two commands an operator needs are the same across all three menu apps.
Consequences: the app is not published on a host port at all — only Caddy, on
the shared Podman network, can reach it — and deployment, logs and restarts move
from docker to systemctl --user / podman. The data root moves to
~/podman-data/menu-<site>, so each Site's content has to be copied across from
/var/lib/menu.<domain> once, before DNS points at it.