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:
1 parent
c412181159
commit
e68f8ab00d
23 files changed
+876
-389
No files matched your search
@@ -1,14 +1,29 @@
|
||||
---
|
||||
# Append this Site's block to the shared Caddyfile.
|
||||
#
|
||||
# Caddy is its own playbook (ansible-playbooks/caddy/playbook.yml) and a rootless
|
||||
# Quadlet unit there, so this role does not manage the container — it only points
|
||||
# it at the app. The Caddyfile is a bind mount into that container, so Caddy sees
|
||||
# a written change as soon as the file lands; the handler only asks Caddy to
|
||||
# re-read it. That is a reload, not a restart, so the other hosted sites are
|
||||
# untouched.
|
||||
#
|
||||
# blockinfile is idempotent on its own via the marker, so there is no need to
|
||||
# slurp the file and compare first — which also matters because slurp *fails*
|
||||
# when the Caddyfile does not exist yet, on a host where the Caddy playbook has
|
||||
# not run.
|
||||
|
||||
- name: Check the Caddyfile exists
|
||||
stat:
|
||||
ansible.builtin.stat:
|
||||
path: '{{ caddyfile_path }}'
|
||||
register: menu_caddyfile
|
||||
|
||||
- name: Fail when Caddy is not where we expect it
|
||||
fail:
|
||||
ansible.builtin.fail:
|
||||
msg: >-
|
||||
{{ caddyfile_path }} is missing. Deploy the caddy playbook, which owns the
|
||||
Caddy container and its config, before this one.
|
||||
{{ caddyfile_path }} is missing. Deploy the Caddy playbook
|
||||
(ansible-playbooks/caddy/playbook.yml), which owns the Caddy unit and its
|
||||
config, before this one.
|
||||
when: not menu_caddyfile.stat.exists
|
||||
|
||||
# The Site's web address may still be claimed by an older snippet: the retired
|
||||
@@ -16,7 +31,7 @@
|
||||
# Caddy refuse the whole config, and a refused reload leaves the old proxy in
|
||||
# place, which is a 502 once the old container is gone.
|
||||
- name: Drop any older snippet claiming this web address
|
||||
blockinfile:
|
||||
ansible.builtin.blockinfile:
|
||||
path: '{{ caddyfile_path }}'
|
||||
marker: '# {mark} Ansible managed Caddy snippet for {{ host }}'
|
||||
state: absent
|
||||
@@ -25,9 +40,12 @@
|
||||
# blockinfile replaces whatever sits between its markers, so redeploying updates
|
||||
# the snippet in place rather than appending a second one.
|
||||
- name: Point the Site's web address at the app
|
||||
blockinfile:
|
||||
ansible.builtin.blockinfile:
|
||||
path: '{{ caddyfile_path }}'
|
||||
marker: '# {mark} ANSIBLE MANAGED: menu app ({{ site }})'
|
||||
block: '{{ caddy_snippet }}'
|
||||
create: no
|
||||
create: false
|
||||
owner: '{{ podman_user }}'
|
||||
group: '{{ podman_user }}'
|
||||
mode: '0644'
|
||||
notify: Reload Caddy
|
||||
Reference in new issue
Block a user