From e0a5753f1a5d4812004690c84424dd7908335c80 Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Mon, 22 Jun 2026 22:03:35 +0200 Subject: [PATCH] fix(deploy): force-recreate caddy on its roll so config-only changes apply The prod rolling deploy rolls each service with `compose up -d --no-deps `. For caddy that is a no-op on a config-only release: its image is pinned (caddy:2-alpine, no $TAG), so the compose definition is unchanged between releases, compose treats the container as current and does not recreate it, and admin is off so there is no hot reload. The new bind-mounted Caddyfile is seeded to the host but never loaded -- the v1.2.2 `Alt-Svc: clear` edge fix deployed green yet did not take effect until caddy was restarted by hand. Force a recreate for caddy on its roll (every other service already recreates on its new $TAG image), so a bind-mounted Caddyfile change always applies. Costs a ~1-2s caddy blip per deploy, acceptable for the infrequent manual prod rollout. --- deploy/README.md | 4 +++- deploy/prod-deploy.sh | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index 89fa882..f8b4a12 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -150,7 +150,9 @@ Re-run `ansible/` after a host resize — it is idempotent. workflow manually (Gitea → Actions → prod-deploy → run from `master`, input `confirm=deploy`). It builds + pushes the images to the registry, ships the compose/config/certs/env over SSH, deploys the main host with `prod-deploy.sh` (rolling, -health-gated, **auto-rollback to the previous tag**), then the bot host, then probes the +health-gated, **auto-rollback to the previous tag**; caddy is force-recreated on its roll so +a bind-mounted `Caddyfile` change applies — its image is pinned and admin is off, so neither a +new tag nor a hot reload would pick it up), then the bot host, then probes the public site. After `master` is green this workflow is the **only** thing that touches prod — nothing auto-deploys there. It runs four visible jobs: **build → deploy-main → deploy-bot → verify** (the per-service rolling shows in the deploy-main log). diff --git a/deploy/prod-deploy.sh b/deploy/prod-deploy.sh index c2fef68..af87062 100755 --- a/deploy/prod-deploy.sh +++ b/deploy/prod-deploy.sh @@ -74,7 +74,13 @@ health_running() { # health_running : running, not restarting, stable roll() { # roll local svc="$1"; shift echo ">>> rolling $svc -> $TAG" - dc up -d --no-build --no-deps "$svc" || return 1 + # caddy's image is pinned (caddy:2-alpine, no $TAG) and its Caddyfile is bind-mounted, so a + # config-only change leaves the compose definition unchanged: `up -d` treats the container as + # current and does not recreate it, and admin is off so there is no hot reload — the new + # Caddyfile would never load. Force a recreate for caddy so config changes always apply; every + # other service already recreates on its new $TAG image. + local recreate=(); [ "$svc" = caddy ] && recreate=(--force-recreate) + dc up -d --no-build --no-deps "${recreate[@]}" "$svc" || return 1 "$@" || { echo "!!! $svc failed health check"; return 1; } echo "<<< $svc healthy" }