From 57c29f1a7facff87596969da6c356c7e30f49008 Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 29 Oct 2026 22:08:34 -0600 Subject: [PATCH] Stop regenerating the dir2opds hash so Caddy isn't restarted every run bcrypt uses a random salt, so hashing the basic auth password on every run changed the Caddyfile each time and triggered the Caddy restart handler. Reuse the deployed hash while it still matches the vault password, and only make a new one when it doesn't (or on a fresh host). The old awk also turned htpasswd's trailing blank line into a stray line in the Caddyfile; the next deploy removes it once. Co-Authored-By: Claude Opus 5.5 --- roles/docker/tasks/infrastructure/caddy.yml | 22 +++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/roles/docker/tasks/infrastructure/caddy.yml b/roles/docker/tasks/infrastructure/caddy.yml index 6fa3c79..c4dff8d 100644 --- a/roles/docker/tasks/infrastructure/caddy.yml +++ b/roles/docker/tasks/infrastructure/caddy.yml @@ -14,11 +14,29 @@ become: true when: vault_dir2opds is defined -- name: Generate bcrypt hash for dir2opds basic auth +# bcrypt uses a random salt, so a fresh hash would change the Caddyfile (and +# restart Caddy) on every run. Reuse the deployed hash while it still matches +# the vault password; only make a new one when it doesn't. +- name: Get bcrypt hash for dir2opds basic auth ansible.builtin.shell: | - htpasswd -bnB "{{ vault_dir2opds.basic_auth_user }}" "{{ vault_dir2opds.basic_auth_password }}" | awk -F: '{print $1, $2}' + set -eu + cur=$(awk -v u="$AUTH_USER" '/basic_?auth/ {b=1} b && $1 == u {print $2; exit}' \ + /opt/stacks/caddy/Caddyfile 2>/dev/null || true) + if [ -n "$cur" ]; then + tmp=$(mktemp); trap 'rm -f "$tmp"' EXIT + printf '%s:%s\n' "$AUTH_USER" "$cur" > "$tmp" + if htpasswd -vb "$tmp" "$AUTH_USER" "$AUTH_PASS" >/dev/null 2>&1; then + echo "$AUTH_USER $cur" + exit 0 + fi + fi + htpasswd -bnB "$AUTH_USER" "$AUTH_PASS" | awk -F: 'NF {print $1, $2}' + environment: + AUTH_USER: "{{ vault_dir2opds.basic_auth_user }}" + AUTH_PASS: "{{ vault_dir2opds.basic_auth_password }}" register: dir2opds_basic_auth_hash_result changed_when: false + check_mode: false no_log: true when: vault_dir2opds is defined