Cut the comment bloat from the Podman playbooks

Comment blocks now stay within three lines and explain only the non-obvious. Long histories, include examples, and commented-out code are gone. No task, key, or value changed; the only data change is comment text inside the generated unit files.
This commit is contained in:
tanshu committed 2026-10-18 22:10:57 +05:30
1 parent 2aab1aec1e
commit 476a6d7cd0
85 files changed
+372 -2433

No files matched your search

+4 -17
View File
@@ -1,27 +1,14 @@
---
# Caddy is its own playbook (caddy/playbook.yml) and a rootless Quadlet unit
# there. These handlers run as the connection user, which is what makes
# `systemctl --user` and `podman exec` work here.
# Notified by this role 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.
# A reload keeps existing connections. A restart would briefly drop every hosted site.
# The config path is inside the container, not caddyfile_path on the host.
- name: Reload Caddy configuration
ansible.builtin.command: >-
podman exec {{ caddy_name }} caddy reload --config /etc/caddy/Caddyfile
changed_when: true
listen: "Reload Caddy"
# Notified by caddy/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. See caddy/readme.md,
# "Trade-off worth knowing".
#
# Defined after the reload above so that when both are notified the cheap
# config reload happens first.
# Quadlet has no live equivalent of network connect, so Caddy is recreated and every hosted site restarts.
# Defined after the reload so the cheap reload runs first.
- name: Restart Caddy
ansible.builtin.systemd_service:
name: "{{ caddy_name }}.service"
-13
View File
@@ -1,17 +1,4 @@
---
# Append this site's block 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 the Caddy playbook has
# not run.
#
# The marker is stable, so re-runs replace this site's block in place rather than
# appending a second copy of it.
- name: "Add the {{ host }} site block to the Caddyfile"
ansible.builtin.blockinfile:
path: "{{ caddyfile_path }}"
+2 -8
View File
@@ -1,17 +1,11 @@
---
# Handlers run as the connection user, which is what makes `systemctl --user`
# work here.
- name: Reload systemd user units
ansible.builtin.command: systemctl --user daemon-reload
changed_when: true
listen: Reload systemd user units
# A changed environment file or unit file changes the generated unit, so
# Nextcloud is recreated. Nothing is lost by that: config.php, data/ and
# custom_apps/ are on the bind mount and the database is in Postgres. It is still
# a few seconds of downtime for the site, and the entrypoint re-runs its version
# check — including `occ upgrade` if the image has moved on — on the way back up.
# Config, data, and custom_apps are on the bind mount, and the database is in Postgres.
# The entrypoint reruns its version check, including occ upgrade, on the way back up.
- name: Restart Nextcloud
ansible.builtin.systemd_service:
name: "{{ unit_name }}"
+7 -29
View File
@@ -1,14 +1,4 @@
---
# Nextcloud as a rootless Podman Quadlet unit.
#
# Everything runs as the connection user; requires gather_facts (set in
# playbook.yml), which is where podman_user and the home directory come from.
#
# A fresh webroot is a valid state. The image initialises the code and serves the
# setup wizard, and this play succeeds. Set nextcloud_admin_user and
# nextcloud_admin_password in vars/default.yml to have it installed unattended
# instead.
- name: Ensure the webroot exists
ansible.builtin.file:
path: "{{ host_directory }}"
@@ -17,9 +7,7 @@
group: "{{ podman_user }}"
mode: '0755'
# Read by the entrypoint, not by Ansible, so it has to exist before the unit
# starts. Mode 0600: POSTGRES_PASSWORD is in it, and the unit file is
# world-readable.
# The entrypoint reads this before the unit starts, and POSTGRES_PASSWORD means it stays 0600.
- name: Write the environment file
ansible.builtin.template:
src: nextcloud.env.j2
@@ -40,8 +28,7 @@
- Reload systemd user units
- Restart Nextcloud
# Quadlet applies [Install] WantedBy= when it generates the unit, so a generated
# unit is never `systemctl enable`d.
# Quadlet applies [Install] WantedBy= when it generates the unit, so it is never enabled.
- name: Start Nextcloud and wait for it to serve
block:
- name: Start Nextcloud
@@ -51,13 +38,8 @@
state: started
daemon_reload: true
# `systemctl start` returns while the unit is still `activating`, and a
# crash-looping container is `activating` most of the time as well, so
# is-active proves nothing. status.php is Nextcloud's own endpoint: it answers
# only once the entrypoint has finished (including any `occ upgrade`) and
# Apache is up, it reports `installed` either way — so one gate fits both a
# fresh webroot and an update — and `maintenance` is in it too, because a
# maintenance-mode 503 on every page is otherwise invisible to a probe.
# `systemctl start` returns while the unit is still activating, and a crash loop looks the same.
# status.php answers after the entrypoint and Apache are ready, and it reports maintenance mode.
- name: Wait for Nextcloud to serve status.php
ansible.builtin.command: >-
podman exec {{ container_name }} php -r
@@ -70,8 +52,7 @@
delay: 5
changed_when: false
rescue:
# systemd reports "control process exited with error code" and nothing else.
# The reason is in the entrypoint's own output.
# systemd only reports "control process exited with error code", so read the entrypoint output.
- name: Collect diagnostics
ansible.builtin.command: "{{ item }}"
loop:
@@ -94,11 +75,8 @@
this playbook has produced before. If the unit is in the `failed` state
from an earlier attempt: systemctl --user reset-failed {{ unit_name }}
# Nextcloud wants `cron.php` every five minutes. This has to be *this user's*
# crontab, not root's: root cannot `podman exec` into another user's rootless
# containers. It works without any environment plumbing because the caddy
# playbook enables lingering, so /run/user/<uid> exists whether or not anyone is
# logged in — which is where podman keeps the state `exec` needs.
# This must be the connection user's crontab. Root cannot podman exec into another user's rootless containers.
# Lingering keeps /run/user/<uid> present, which is where podman keeps the state exec needs.
- name: Schedule Nextcloud's background jobs
ansible.builtin.cron:
name: Nextcloud background jobs
+1 -9
View File
@@ -1,13 +1,5 @@
---
# Postgres is its own playbook (postgres/playbook.yml) and a rootless Quadlet
# unit there. This handler runs as the connection user, which is what makes
# `systemctl --user` work here.
#
# Required by postgres/roles/attach, which notifies it whenever this app's
# drop-in changes: a new drop-in changes the generated unit, so Postgres must be
# recreated to join the network — Quadlet has no live equivalent of
# `podman network connect`. That is a few seconds of downtime for every attached
# app, not just this one. See postgres/readme.md, "The trade-off".
# A new drop-in changes the generated unit, so Postgres is recreated and every attached app restarts.
- name: Restart Postgres
ansible.builtin.systemd_service:
name: "{{ postgres_unit }}"
+2 -11
View File
@@ -1,21 +1,12 @@
---
# Attach this app's network to the shared Postgres unit, and make sure the
# database exists.
- name: Attach Nextcloud to Postgres
ansible.builtin.include_tasks: "{{ playbook_dir }}/../postgres/roles/attach/tasks/main.yaml"
# The restart that joins Postgres to nextcloud_net is a handler, so by default it
# would run at the end of the play — after the app has started and failed to
# resolve `db`. Flushing first also applies the Caddy restart queued by the
# register pre_task. Nothing is pending on later runs.
# The restart that joins Postgres to nextcloud_net is a handler, so flush it before the app starts. This also applies the queued Caddy restart.
- name: Apply the network change before starting Nextcloud
ansible.builtin.meta: flush_handlers
# Postgres ships one default database and only this app knows the name of its own,
# so on a fresh cluster the installer would otherwise fail with "database
# nextcloud does not exist". The retry is for the restart the flush above may have
# just done.
# On a fresh cluster the installer would fail without this database, and the retry covers the restart the flush did.
- name: Check whether the {{ pg_database }} database exists
ansible.builtin.command: >-
podman exec -e PGPASSWORD={{ pg_password }} {{ postgres_container }}
+2 -14
View File
@@ -1,18 +1,6 @@
---
# Valkey is its own playbook (valkey/playbook.yml) and a rootless Quadlet unit
# there. This handler runs as the connection user, which is what makes
# `systemctl --user` work here.
#
# Required by valkey/roles/attach, which notifies it whenever this app's drop-in
# changes: a new drop-in changes the generated unit, so Valkey must be recreated
# to join the network — Quadlet has no live equivalent of
# `podman network connect`.
#
# Data survives the recreate: RDB persistence is on by default, the stop is
# graceful, and the new container loads the snapshot back off the bind mount. What
# does not survive is availability — for the seconds the container is down,
# Nextcloud's PHP sessions and `memcache.locking` are unreachable. See
# valkey/readme.md, "The trade-off".
# A new drop-in changes the generated unit, so Valkey is recreated to join the network.
# Data survives the recreate, but Nextcloud's cache and locks are unavailable for the seconds it is down.
- name: Restart Valkey
ansible.builtin.systemd_service:
name: "{{ valkey_unit }}"
+2 -22
View File
@@ -1,28 +1,8 @@
---
# Attach this app's network to the shared Valkey unit.
#
# Valkey knows nothing about its clients, exactly like Caddy and Postgres: a
# service joins by dropping 50-nextcloud.conf and the shared
# 10-network-aliases.conf next to valkey.container. The canonical way to do that
# is the shared include below — it writes the same bytes every service writes,
# asserts that nextcloud.network already exists, and notifies the "Restart
# Valkey" handler defined in this role.
#
# `redis` is the alias the app connects to, not the container name: it is the host
# an instance configured for Redis has in config.php. This playbook does not write
# that configuration, it only makes the name resolvable.
# The app connects to `redis`, the alias the attach role adds, not the container name.
- name: Attach Nextcloud to Valkey
ansible.builtin.include_tasks: "{{ playbook_dir }}/../valkey/roles/attach/tasks/main.yaml"
# On a first attach the drop-in is new, so Valkey has to be recreated to join
# nextcloud_net — and that restart is a *handler*, which by default runs at the
# end of the play, after the nextcloud role has already started the app. The app
# would then come up before `redis` resolves; with `memcache.locking` on Redis it
# would fail on the first write rather than at startup, which is a worse failure
# to debug.
#
# Flushing applies the new drop-in before the app starts. On later runs the
# drop-in is unchanged, nothing is pending, and this is a no-op.
# The restart that joins Valkey to nextcloud_net is a handler, so flush it before the app starts or it fails on the first cache write.
- name: Apply the Valkey network change before starting Nextcloud
ansible.builtin.meta: flush_handlers