Run the build on Podman and deploy as a rootless Podman Quadlet

- Makefile: podman build + push instead of docker buildx. build-production
  clones the git remote and builds from it; build-check / build-check-local
  build without pushing. Single-architecture (PLATFORM-overridable) rather
  than a multi-arch manifest.
- deploy.sh: connect as the unprivileged container user; no become.
- ansible: target emily, rootless Podman Quadlet behind the fleet's shared
  Caddy unit (caddy/playbook.yml in ansible-playbooks).
  - register role writes greatbear.network (NetworkName=greatbear_net) and
    the caddy.container.d drop-in that puts Caddy on it.
  - greatbear role: podman login/pull, ~/podman-data/greatbear + .env,
    greatbear.container (UserNS=keep-id:uid=0,gid=0, EnvironmentFile,
    Network, Volume, no published ports), systemctl --user start and a
    podman healthcheck gate, with a diagnostics rescue block.
  - caddy role appends the site blocks to the shared Caddyfile and reloads;
    handlers reload vs. recreate Caddy (a new network drop-in re-creates it).
  - drop the network role, the community.docker requirements and the
    ansible/files/ templates.
- .containerignore replaces .dockerignore (Buildah reads it natively).
- README: Podman build, rootless Quadlet deploy. No data migration step —
  there is no PocketBase state to carry over.
This commit is contained in:
tanshu committed 2026-10-16 10:09:12 +05:30
1 parent d9ba227657
commit 9620847108
17 files changed
+523 -183

No files matched your search

-3
View File
@@ -1,3 +0,0 @@
---
caddy_container: caddy
caddy_caddyfile_path: /var/lib/caddy/conf/Caddyfile
+28 -2
View File
@@ -1,5 +1,31 @@
---
# Caddy is its own playbook (caddy/playbook.yml in the ansible-playbooks repo)
# and a rootless Quadlet unit there. These handlers run as the connection user,
# so `systemctl --user` and `podman exec` work without any XDG_RUNTIME_DIR
# juggling.
# Notified by roles/caddy when the Caddyfile changes. A reload keeps existing
# connections; a restart would briefly drop every hosted site.
#
# Note the config path: /etc/caddy/Caddyfile is the mount inside the container,
# not {{ caddyfile_path }}, which is the host side of it.
- name: Reload Caddy configuration
ansible.builtin.command: "docker exec -w /etc/caddy {{ caddy_container }} caddy reload"
listen: "Reload Caddy"
ansible.builtin.command: >-
podman exec {{ caddy_name }} caddy reload --config /etc/caddy/Caddyfile
changed_when: true
listen: "Reload Caddy"
# Notified by roles/register when this service's network unit, or the drop-in
# that attaches Caddy to it, is written. Quadlet has no live equivalent of
# `docker network connect`, so the container has to be recreated — a brief
# restart of every hosted site, not just this one.
#
# Defined after the reload above so that when both are notified the cheap config
# reload happens first.
- name: Restart Caddy
ansible.builtin.systemd_service:
name: "{{ caddy_name }}.service"
scope: user
state: restarted
daemon_reload: true
listen: Restart Caddy
+17 -21
View File
@@ -1,26 +1,22 @@
---
- name: Read snippet from template file
ansible.builtin.set_fact:
caddy_snippet_block: "{{ lookup('template', 'files/Caddyfile.j2') }}"
# Append The Great Bear's site blocks to the shared Caddyfile.
#
# The Caddyfile is a bind mount into the Caddy container, so Caddy sees the
# change as soon as the file is written; 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 caddy/playbook.yml has
# not run.
- name: Read current Caddyfile
ansible.builtin.slurp:
path: "{{ caddy_caddyfile_path }}"
register: caddy_caddyfile_raw
- name: Decode Caddyfile content
ansible.builtin.set_fact:
caddy_caddyfile_content: "{{ caddy_caddyfile_raw['content'] | b64decode }}"
- name: Check if snippet already exists
ansible.builtin.set_fact:
caddy_snippet_present: "{{ caddy_snippet_block in caddy_caddyfile_content }}"
- name: Add or update snippet in Caddyfile
- name: "Add the {{ host }} site blocks to the Caddyfile"
ansible.builtin.blockinfile:
path: "{{ caddy_caddyfile_path }}"
path: "{{ caddyfile_path }}"
marker: "# {mark} Ansible managed Caddy snippet for {{ host }}"
block: "{{ caddy_snippet_block }}"
block: "{{ snippet_block }}"
create: true
mode: "0644"
notify: Reload Caddy configuration
owner: "{{ podman_user }}"
group: "{{ podman_user }}"
mode: '0644'
notify: Reload Caddy