The deploy failed in the network role: the Caddy restart exited 125 with
"unable to find network with name or ID mozimo_net", and with Restart=always
and a 100ms delay the start limit was spent in under a second — taking every
other site this host serves down with it.
The network was gone, but mozimo-network.service was not: it is a oneshot with
RemainAfterExit=yes, so systemd kept reporting it active after the network had
been removed out of band. The generated Requires=mozimo-network.service looked
satisfied, so the flushed "Restart Caddy" handler started Caddy against a
network that no longer existed, and nothing recreated it.
- ansible/roles/network/tasks/main.yaml: daemon-reload after templating the
unit so it can be started on a first deploy; ask podman (`podman network
exists`) rather than systemd whether the network is really there; restart
mozimo-network.service when it is not; confirm it exists before the handler
flush, so a network that cannot be repaired fails the play rather than the
host's reverse proxy.
- The Caddy restart condition includes the recreated case: a network that
comes back keeps its name but not its identity, so Caddy's network namespace
is stale even when neither template changed.
- ansible/README.md: the oneshot/stale-state trap and the manual recovery.
Verified on emily after recovering Caddy by hand: the play completes with
22 ok / 6 changed / 0 failed, and mozimo and vince run behind Caddy (TLS for
mozimo.in still waits on the DNS cutover).
Retargets the build and the playbook off rootful Docker on monoco, following the
conventions already in place on emily's other services: Quadlet units in
~/.config/containers/systemd, per-service data in ~/podman-data, and a shared
Caddy that every service registers itself with — a network drop-in plus a
marked block in its Caddyfile. Nothing is published on the host; Caddy reaches
the containers by name over mozimo_net.
- Makefile: podman build + push instead of docker buildx, PLATFORMS=linux/arm64
(both hosts are aarch64). podman has no built-in QEMU the way buildx's builder
image does, so a foreign-platform failure now points at qemu-user-static.
- deploy.sh: pass COMMIT= to make, which the Makefile actually reads; it was
passing TAG=, so the tag silently came from `git rev-parse` instead.
- ansible: hosts emily, become false, XDG_RUNTIME_DIR for rootless podman and
systemctl --user. Docker modules become Quadlet templates with user-service
handlers, and the network role now ships mozimo.network plus the Caddy drop-in
rather than calling docker_network.
- UserNS=keep-id maps the container's uid 1000 (node) and root (vince) onto the
host user, so PocketBase and Vince write host-owned files instead of
subuid-owned ones; the play asserts the pinned uid still matches the host.
- ansible/README.md: the unit layout, the service-registration convention, and
the monoco -> emily migration (PocketBase 23 MB + Vince 119 MB, DNS cutover,
rollback).
Verified by a check-mode rehearsal against emily (13 ok / 8 changed / 0 failed)
and a disposable Quadlet unit on that host proving the uid mapping, the
EnvironmentFile and the isolated network. The real build and cutover have not
been run.