From e18e0d51a08945b90375dcf446a364ac14c71e91 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Tue, 2 Jun 2026 21:50:38 +0000 Subject: [PATCH] uptime-kuma: public status pages + push monitors bypass Authentik MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The single uptime ingress gated the ENTIRE site (path "/") behind Authentik forward-auth, so public-by-design endpoints 302-bounced to SSO: status pages (/status/), push-monitor ingest (/api/push/), status-page API + heartbeat (/api/status-page), badges (/api/badge), and static assets. Status pages are for logged-out viewers and push monitors POST from machines — neither can follow the Authentik OAuth cookie dance, so all were broken. Fix mirrors the meshcentral agent carve-out (9a15f3f2): add a second path-scoped ingress_factory (auth="none") pointing at the same uptime-kuma Service. Traefik routes longest-rule-first, so these out-prioritise the "/" catch-all; the dashboard (/, /dashboard, /manage-*, /settings, etc.) stays Authentik-gated via the original ingress. WebSocket status UI keeps working — the default middleware chain passes Upgrade/Connection through. Verified: /status/infra, /api/status-page/{,heartbeat/}infra, /api/badge no longer 302 (200); / still 302s to authentik. Co-Authored-By: Claude Opus 4.7 --- .../uptime-kuma/modules/uptime-kuma/main.tf | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/stacks/uptime-kuma/modules/uptime-kuma/main.tf b/stacks/uptime-kuma/modules/uptime-kuma/main.tf index 5e2e12c0..2aee365f 100644 --- a/stacks/uptime-kuma/modules/uptime-kuma/main.tf +++ b/stacks/uptime-kuma/modules/uptime-kuma/main.tf @@ -241,6 +241,44 @@ module "ingress" { } } +# Path-level carve-out for Uptime Kuma's public-by-design endpoints. +# The main ingress above gates the ENTIRE site (path "/") behind Authentik +# forward-auth — which 302-bounces the public status pages, push-monitor +# ingest, status-page API, badges, and static assets to the SSO login. Status +# pages are meant for logged-out viewers and push monitors POST from machines; +# neither can follow the Authentik 302 → OAuth → cookie dance, so all of these +# were broken (302 instead of 200/JSON). This second ingress points the public +# paths at the same uptime-kuma Service with NO Authentik middleware. Traefik +# routes by rule length, so these path-scoped routers out-prioritise the "/" +# catch-all (same mechanism as the meshcentral agent carve-out, commit +# 9a15f3f2). The dashboard ("/", "/dashboard", "/manage-*", "/add", "/edit", +# "/settings", "/setup") stays Authentik-gated via the module above. Uptime +# Kuma is WebSocket-based; the ingress_factory default middleware chain passes +# Upgrade/Connection through unchanged, so the realtime status UI still works. +module "ingress_public" { + source = "../../../../modules/kubernetes/ingress_factory" + namespace = kubernetes_namespace.uptime-kuma.metadata[0].name + name = "uptime-public" + service_name = "uptime-kuma" + # auth = "none": Uptime Kuma public status pages + push-monitor/badge endpoints - hit logged-out / by machines, cannot do Authentik SSO + auth = "none" + ingress_path = [ + "/status", # public status pages (/status/) + "/api/status-page", # status-page data + heartbeat API + "/api/push", # push-monitor ingest (/api/push/) + "/api/badge", # status/uptime/ping badges + "/assets", # JS/CSS/font bundles for the status page + "/icon.svg", # favicon / logo + "/upload", # uploaded status-page logos/images + ] + full_host = "uptime.viktorbarzin.me" + dns_type = "none" # DNS already owned by the main uptime ingress above. + tls_secret_name = var.tls_secret_name + anti_ai_scraping = false # Status pages + push ingest are machine/anon-hit; bot-block forwardAuth would break them. + homepage_enabled = false # Homepage tile belongs to the main UI ingress. + external_monitor = false # The main ingress already carries the external monitor. +} + # CronJob for daily SQLite backups # no longer needed as we're using the mysql # resource "kubernetes_cron_job_v1" "sqlite-backup" { # metadata {