Run the Sites as rootless Podman Quadlets, and build with podman

The fleet on emily is rootless Podman with Quadlet units under
~/.config/containers/systemd and state in ~/podman-data, all behind one shared
Caddy unit. This brings the menus in line instead of leaving them the last
Docker deployment. The build moves with them: podman reads a Containerfile as
readily as a Dockerfile, so the name now says which toolchain is real.

The app is one .container and one .network file. Two details carry it.
UserNS=keep-id maps the image's own node account onto the user that owns the
units, so data/ and site.env stay owned by tanshu: plain tar backups, no
subuids. provision-site-env.sh writes site.env with the same mapping rather
than --user, which under rootless Podman would have produced a subuid-owned
file the app could not read. 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 changes when a Site is added. The unit keeps the Docker-era container
name for the scripts and muscle memory that look it up, while the Caddyfile
proxies to a dotless NetworkAlias, because a container name with dots in it is
a liability in DNS.

The unit keeps podman's Pull=missing, so a restart or a reboot never depends on
the registry being reachable, while the play pulls explicitly at deploy time.
That is also where a missing `podman login` for the private registry now fails,
with the instruction, rather than as a unit that will not start.

copy-site-data.sh moves a Site's data across, and is not a plain rsync:
/var/lib/menu.* on monoco belongs to uid 1000 while the ssh user there is 1001,
so the read needs sudo; monoco cannot ssh to emily, so the workstation relays
the tar; and the extraction runs as tanshu on emily, which is what makes the
files land owned by the user keep-id maps the app onto. It proves the copy by
comparing a SHA-256 of the whole tree against the source and checking every
file's owner.

Not yet done: the copies themselves and the DNS move, which need a human.
This commit is contained in:
tanshu committed 2026-10-16 09:54:52 +05:30
1 parent c412181159
commit e68f8ab00d
23 files changed
+876 -389

No files matched your search

+8 -1
View File
@@ -1,7 +1,9 @@
#!/usr/bin/env bash
#
# Builds the image with podman, pushes it to the private registry, then deploys
# the Site with the playbook that lives in ansible/.
# the Site with the playbook that lives in ansible/. The playbook runs rootless
# Podman Quadlet units on emily, behind the shared Caddy unit from
# ansible-playbooks/caddy.
#
# ./deploy.sh 2026-09-22 deploy the default Site
# SITE=greatbear ./deploy.sh 2026-09-22 deploy another Site
@@ -24,6 +26,11 @@ if ! command -v podman >/dev/null 2>&1; then
exit 1
fi
if [[ -z "${SKIP_DEPLOY:-}" ]] && ! command -v ansible-playbook >/dev/null 2>&1; then
echo "ansible-playbook is required to deploy; SKIP_DEPLOY=1 builds and pushes only" >&2
exit 1
fi
if [[ -z "${SKIP_CHECKS:-}" ]]; then
echo "==> lint, format, types and tests"
npm run lint