DC-044: fix /health/ready caddy probe false negative
The caddy.ok check in /health/ready probed /config/ (51KB) and timed out at 3s with "This operation was aborted" while Caddy admin was actually healthy. Two underlying issues: 1. Native undici fetch() rejects connections to :2019 (Caddy admin). Use fetchT() which falls back to raw http.request for the admin port. 2. /config/ is heavy and head-of-line blocks when /load is in flight. Switch to /config/apps/http/servers/srv0/listen (9 bytes) and bump timeout to 10s. Verified on DNS2 2026-07-09: direct Caddy admin curl 200 in 3ms, /health/ready was aborting at 3s. After fix: /health/ready caddy.ok true in <100ms. Caddyfile change (/etc/caddy/Caddyfile) added /dashcaddy-login to the @needsAuth not path exclude so direct hits to the auto-login landing page render the page instead of getting gate-redirected to a blank 302 — applied and reloaded via POST /load earlier this session.
This commit is contained in:
@@ -105,10 +105,7 @@ function buildApp({ configOk = true, servicesOk = true, dockerOk = true, caddyOk
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
||||||
const controller = new AbortController();
|
const response = await fetch(`${caddyUrl}/config/apps/http/servers/srv0/listen`, { signal: AbortSignal.timeout(10000) });
|
||||||
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
||||||
const response = await fetch(`${caddyUrl}/config/`, { signal: controller.signal });
|
|
||||||
clearTimeout(timeout);
|
|
||||||
checks.caddy = { ok: response.ok, status: response.status };
|
checks.caddy = { ok: response.ok, status: response.status };
|
||||||
if (!response.ok) allOk = false;
|
if (!response.ok) allOk = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -109,10 +109,7 @@ function buildApp({ configOk = true, servicesOk = true, dockerOk = true } = {})
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
||||||
const controller = new AbortController();
|
const response = await fetch(`${caddyUrl}/config/apps/http/servers/srv0/listen`, { signal: AbortSignal.timeout(10000) });
|
||||||
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
||||||
const response = await fetch(`${caddyUrl}/config/`, { signal: controller.signal });
|
|
||||||
clearTimeout(timeout);
|
|
||||||
checks.caddy = { ok: response.ok, status: response.status };
|
checks.caddy = { ok: response.ok, status: response.status };
|
||||||
if (!response.ok) allOk = false;
|
if (!response.ok) allOk = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -727,14 +727,14 @@ async function createApp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check 4: Caddy admin API reachable
|
// Check 4: Caddy admin API reachable
|
||||||
|
// Use fetchT() (NOT native fetch) because undici fetch rejects Caddy admin
|
||||||
|
// on :2019, and probe the LIGHTEST endpoint (srv0/listen = 9 bytes) to avoid
|
||||||
|
// head-of-line blocking when /load or another config mutation is in flight.
|
||||||
|
// A previous `/config/` probe hit the 3s AbortController timeout with
|
||||||
|
// "This operation was aborted" while Caddy was actually healthy.
|
||||||
try {
|
try {
|
||||||
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
||||||
const controller = new AbortController();
|
const response = await fetchT(`${caddyUrl}/config/apps/http/servers/srv0/listen`, {}, 10000);
|
||||||
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
||||||
const response = await fetch(`${caddyUrl}/config/`, {
|
|
||||||
signal: controller.signal
|
|
||||||
});
|
|
||||||
clearTimeout(timeout);
|
|
||||||
checks.caddy = { ok: response.ok, status: response.status };
|
checks.caddy = { ok: response.ok, status: response.status };
|
||||||
if (!response.ok) allOk = false;
|
if (!response.ok) allOk = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user