Skip to content

fix(ssl): save port 80 stop/start hooks for standalone renewals - #38

Merged
MarkProminic merged 1 commit into
mainfrom
fix/ssl-standalone-renewal-hooks-37
Oct 28, 2026
Merged

MarkProminic merged 1 commit into
mainfrom
fix/ssl-standalone-renewal-hooks-37

Conversation

@solaechea

Copy link
Copy Markdown
Contributor

Written with Claude Opus 5.5

Fixes #37.

Change

In roles/ssl/tasks/debian.yml, the two standalone requests that answer on port 80 (staging and production, without HAProxy) now pass certbot_create_standalone_stop_services to certbot as hooks:

--pre-hook "systemctl stop nginx || true" --post-hook "systemctl start nginx || true"

certbot saves them in the lineage's renewal config, so unattended renewals free port 80 the same way the first issuance does. If the list is empty, no hooks are passed.

The Ansible stop and start tasks around the first issuance stay in place. The HAProxy variants are unchanged, because they answer on port 8181.

Testing

  • Before the change: on a Debian 12 instance whose certificate the role had issued, with nginx on port 80, certbot renew --dry-run --no-random-sleep-on-renew failed: Could not bind TCP port 80 because it is already in use.
  • With the hooks: I added these hooks to that lineage's renewal config, and the same dry run succeeded. nginx was running again afterwards.
  • Rendering: I ran the new task through ansible-core 2.18 and captured the arguments command passes to certbot:
    • with [nginx, haproxy]: '--pre-hook', 'systemctl stop nginx haproxy || true', '--post-hook', 'systemctl start nginx haproxy || true', each hook a single argument;
    • with []: no hook arguments.
  • prettier --check and yamllint pass.

Existing certificates keep their saved renewal config. This only applies to new issuances; older lineages need a re-issue or the hooks added by hand.

The role stopped the port 80 services in Ansible around the first
standalone issuance, so certbot never saved them in the renewal config.
Every unattended renewal then failed to bind port 80 while nginx was
running, and the certificate expired. The same services are now passed
as --pre-hook/--post-hook, which certbot keeps for every renewal.
@MarkProminic
MarkProminic merged commit 6239c48 into main Oct 28, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ssl: standalone Let's Encrypt certificates never renew while nginx holds port 80

2 participants