diff --git a/Caddyfile b/Caddyfile index 2ab5d3c..25cb68a 100644 --- a/Caddyfile +++ b/Caddyfile @@ -170,12 +170,31 @@ # ── SvelteKit UI (catch-all — includes all remaining /api/* routes) ─────── handle { - reverse_proxy ui:3000 + reverse_proxy ui:3000 { + # Active health check: Caddy polls /health every 5 s and marks the + # upstream down immediately when it fails. Combined with + # lb_try_duration this means Watchtower container replacements + # show the maintenance page within a few seconds instead of + # hanging or returning a raw connection error to the browser. + health_uri /health + health_interval 5s + health_timeout 2s + health_status 200 + + # If the upstream is down, fail fast (don't retry for longer than + # 3 s) and let Caddy's handle_errors 502/503 take over. + lb_try_duration 3s + } } # ── Caddy-level error pages ─────────────────────────────────────────────── # These fire when the upstream (backend or ui) is completely unreachable. # SvelteKit's own +error.svelte handles application-level errors (404, 500). + handle_errors 404 { + root * /srv/errors + rewrite * /404.html + file_server + } handle_errors 502 { root * /srv/errors rewrite * /502.html diff --git a/caddy/errors/404.html b/caddy/errors/404.html new file mode 100644 index 0000000..206fc24 --- /dev/null +++ b/caddy/errors/404.html @@ -0,0 +1,51 @@ + + + + + + 404 — Page Not Found + + + +
404
+

Page Not Found

+

The page you're looking for doesn't exist or has been moved.

+ Go home + +