fix: Caddy health check must hit /config/ not /
Unit Tests / test (push) Successful in 7m35s

GET http://cell-caddy:2019/ returns 404 because Caddy's admin API has no
root handler.  The health monitor interpreted every response as a failure,
restarted Caddy every 3 minutes, and prevented ACME from ever completing.

/config/ returns 200 + the running config JSON whenever Caddy is up and
serving — that is the correct liveness indicator.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 15:57:32 -04:00
parent da302b5d54
commit e9077b2633
2 changed files with 9 additions and 4 deletions
+7 -2
View File
@@ -500,9 +500,14 @@ class CaddyManager(BaseServiceManager):
return False
def check_caddy_health(self) -> bool:
"""GET the Caddy admin API root. Returns True on HTTP 200."""
"""GET Caddy's config endpoint. Returns True on HTTP 200.
Caddy's admin API has no root handler — GET / returns 404 even when
fully healthy. GET /config/ returns 200 + the running config JSON
whenever Caddy is up and serving.
"""
try:
resp = requests.get(CADDY_ADMIN_URL + "/", timeout=5)
resp = requests.get(CADDY_ADMIN_URL + "/config/", timeout=5)
except requests.RequestException as e:
logger.debug("Caddy health check error: %s", e)
return False
+2 -2
View File
@@ -241,8 +241,8 @@ class TestHealthCheck(unittest.TestCase):
mock_get.return_value = MagicMock(status_code=200)
self.assertTrue(mgr.check_caddy_health())
mock_get.assert_called_once()
# URL must be the admin API root
self.assertIn('cell-caddy:2019', mock_get.call_args[0][0])
# Must hit /config/ — not the root which returns 404
self.assertIn('/config/', mock_get.call_args[0][0])
def test_returns_false_on_connection_error(self):
mgr = _mgr()