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.
35 lines
2.3 KiB
Markdown
35 lines
2.3 KiB
Markdown
# 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.
|