fix: renew_cert regenerates Caddyfile before reload
Unit Tests / test (push) Successful in 7m32s

A stale or empty-token Caddyfile on disk caused Caddy to reject the
/load request, so the Renew button appeared to do nothing. Now
renew_cert() calls regenerate_with_installed([]) first, which writes a
fresh Caddyfile from current identity/config before reloading Caddy.
This ensures a broken on-disk file never blocks ACME renewal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 14:38:30 -04:00
parent 6bd5f02b03
commit da302b5d54
2 changed files with 21 additions and 10 deletions
+16 -5
View File
@@ -649,11 +649,12 @@ class CaddyManager(BaseServiceManager):
# ── Active cert management ────────────────────────────────────────────
def renew_cert(self) -> Dict[str, Any]:
"""Trigger ACME cert renewal by reloading Caddy.
"""Regenerate the Caddyfile, reload Caddy, and trigger ACME cert renewal.
Returns immediately with status='pending' so the caller can poll
GET /api/caddy/cert-status to track progress. Not applicable to
LAN mode — callers should use upload_custom_cert() instead.
Regenerates first so a stale or broken on-disk Caddyfile never blocks
the reload. Returns immediately with status='pending'; the caller
polls GET /api/caddy/cert-status to track progress. Not applicable
to LAN mode — callers should use upload_custom_cert() instead.
"""
ident = (self.config_manager.get_identity() if self.config_manager else {}) or {}
domain_mode = ident.get('domain_mode', 'lan')
@@ -665,7 +666,17 @@ class CaddyManager(BaseServiceManager):
'Upload a custom certificate instead.',
}
if not self.reload_caddy():
# Regenerate → write → reload in one shot so the Caddyfile is always fresh.
if self.config_manager:
try:
ok = self.regenerate_with_installed([])
except Exception as exc:
logger.error('renew_cert: regenerate_with_installed failed: %s', exc)
ok = False
else:
ok = self.reload_caddy()
if not ok:
return {'ok': False, 'error': 'Caddy reload failed — check Caddy logs.'}
# Invalidate the cached status so the next poll triggers a fresh SSL check.