Renewed is not delivered
Starting point
After the restructuring, the Certbot hooks pointed to a container that no longer existed. I switched them to Traefik, and the dry run passed. On 20 September the cron job renewed both certificates automatically, and the new files were on disk. Everything looked done.
Decision
The hooks only stop Traefik, because that is where the port 80 conflict lies. But the certificate is served by the nginx container, which only reads it at startup. So a deploy hook now brings both containers up to date after every real renewal. A reload was the plan, a restart is what it became. It falls into the pause during which Traefik is stopped for the renewal anyway, and extends it only by the restart’s own duration — in a single measurement roughly 0.7 seconds for both containers, not counting the time nginx takes to shut down.
Implementation
On 30 September, a look at the served expiry dates with openssl s_client against the edge router showed December for odabas.ch and still October for waverider52.com. The file was renewed, but it wasn’t being served. Reloading nginx-waverider broke TLS connections for about 20 minutes, and a restart fixed it. Why the reload caused the problem, I don’t know; the cause is open. The hook lives as a script in Certbot’s deploy folder. In a dry run, deploy hooks only run with --run-deploy-hooks, so an ordinary dry run silently skips them. If the restart itself fails, that only shows up in Certbot’s log and the cron log. The hook script still exits with code 0, the cron job reports success, no mail goes out, and the site would stay unreachable after the renewal — something that would only surface when checking against the running service, which is the plan anyway.
Takeaway
A passing dry run doesn’t prove the renewed certificate is actually served. You check against the running service, not the file. And even a harmless-looking reload on a production service needs a way back. The end-to-end proof is still pending: it comes with the next real renewal in November.