From 3a31b8e6f44828a791e6a9019ebbfa3fff88f426 Mon Sep 17 00:00:00 2001 From: sjat Date: Tue, 16 Jun 2026 07:44:45 +0200 Subject: [PATCH] fix(reverse_proxy): bind-mount the Caddy config dir so reload sees changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Caddyfile was bind-mounted as a single file. ansible.builtin.template writes atomically (temp + rename), so a re-render swaps the file's inode while the running container keeps the old one — `caddy reload` then re-read stale config and silently no-op'd ("config is unchanged"), so new routes never loaded. Surfaced deploying the NetBird route: Caddy never requested its cert. Fix: render to ./caddy/Caddyfile and mount the ./caddy DIRECTORY at /etc/caddy — directory mounts reflect inode swaps, so graceful `caddy reload` works. Proven on askari: atomic replace in the host dir is visible inside the running container. Co-Authored-By: Claude Opus 4.8 (1M context) --- roles/reverse_proxy/molecule/default/verify.yml | 2 +- roles/reverse_proxy/tasks/main.yml | 13 ++++++++++++- roles/reverse_proxy/templates/docker-compose.yml.j2 | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/roles/reverse_proxy/molecule/default/verify.yml b/roles/reverse_proxy/molecule/default/verify.yml index 8316e93..d28e355 100644 --- a/roles/reverse_proxy/molecule/default/verify.yml +++ b/roles/reverse_proxy/molecule/default/verify.yml @@ -6,7 +6,7 @@ tasks: - name: Slurp the rendered Caddyfile ansible.builtin.slurp: - src: /opt/services/reverse_proxy/Caddyfile + src: /opt/services/reverse_proxy/caddy/Caddyfile register: _caddyfile - name: Assert Caddyfile exists and contains expected content ansible.builtin.assert: diff --git a/roles/reverse_proxy/tasks/main.yml b/roles/reverse_proxy/tasks/main.yml index 74c5d19..a89fedc 100644 --- a/roles/reverse_proxy/tasks/main.yml +++ b/roles/reverse_proxy/tasks/main.yml @@ -6,10 +6,21 @@ mode: "0750" tags: [config] +- name: Ensure the Caddy config directory exists + ansible.builtin.file: + path: "{{ reverse_proxy__base_dir }}/caddy" + state: directory + mode: "0750" + tags: [config] + +# Render into a directory that is bind-mounted whole (./caddy -> /etc/caddy). Mounting +# the directory, not the single file, means an atomic template rewrite (which swaps the +# file inode) stays visible inside the running container, so `caddy reload` picks it up. +# A single-file bind mount pins the original inode and reload silently no-ops (ADR-024). - name: Render the Caddyfile ansible.builtin.template: src: Caddyfile.j2 - dest: "{{ reverse_proxy__base_dir }}/Caddyfile" + dest: "{{ reverse_proxy__base_dir }}/caddy/Caddyfile" mode: "0644" notify: reload caddy tags: [config] diff --git a/roles/reverse_proxy/templates/docker-compose.yml.j2 b/roles/reverse_proxy/templates/docker-compose.yml.j2 index 740d187..af34d49 100644 --- a/roles/reverse_proxy/templates/docker-compose.yml.j2 +++ b/roles/reverse_proxy/templates/docker-compose.yml.j2 @@ -12,7 +12,7 @@ services: - ./env {% endif %} volumes: - - ./Caddyfile:/etc/caddy/Caddyfile:ro + - ./caddy:/etc/caddy:ro - caddy_data:/data - caddy_config:/config networks: