grafana: auth_proxy behind the Authentik guard chain
Grafana leaves the exempt-by-construction set: grafana.franksdank.cloud now terminates at the Anubis guard (anubis:8923) and authenticated traffic returns at the internal :8017 listener, where an @grafana Host handler proxies through to grafana:3000 with the outpost-proxy trust token (GRAFANA_PROXY_TOKEN = client_id_client_secret of the new 'grafana-proxy' ProxyProvider on the embedded outpost; created via ak shell before this route flip — provider-first ordering per the External Exposure Policy). The Grafana admin account is intentionally kept: auth.proxy in auto-upsert mode only creates non-admin users, so the local admin remains the only way to administer Grafana. The old edge-basicauth wrapper is retired (shared family password, no per-user audit trail). - Caddyfile: grafana vhost flipped to the guarded chain; @grafana handler added at the :8017 return listener. - compose.yaml: GF_AUTH_PROXY_ENABLED/HEADERS/TOKEN on the grafana service (auth_proxy trusted-proxy CIDRs left at the image default — the proxying Caddy container is not statically addressable on 10.89.0.0/24, so Grafana trusts any in-network source and relies on the token as the capability). - .env.example: GRAFANA_PROXY_TOKEN placeholder so test env_consistency keeps guarding the compose<->env contract.
This commit is contained in:
1 parent
c6d404ffde
commit
ec03929d95
3 files changed
+39
-22
No files matched your search
@@ -20,16 +20,18 @@ WIREGUARD_PERSISTENT_KEEPALIVE_INTERVAL=25s
|
|||||||
# Gitea database
|
# Gitea database
|
||||||
GITEA_DB_PASSWORD=changeme
|
GITEA_DB_PASSWORD=changeme
|
||||||
|
|
||||||
# Grafana admin
|
# Grafana auth-proxy trust token. The outpost proxy provider 'grafana-proxy'
|
||||||
GRAFANA_ADMIN_USER=admin
|
# forwards authenticated traffic to Grafana with Authorization: Bearer
|
||||||
GRAFANA_ADMIN_PASSWORD=changeme
|
# <client_id>_<client_secret>; the live .env must set this to that exact
|
||||||
|
# concatenation (provider created via ak shell on authentik-server).
|
||||||
|
GRAFANA_PROXY_TOKEN=changeme
|
||||||
|
|
||||||
# Caddy (the homelab's single reverse proxy, on this host)
|
# Caddy (the homelab's single reverse proxy, on this host)
|
||||||
# bcrypt hash (caddy hash-password). deploy.sh renders it into
|
# bcrypt hash (caddy hash-password). deploy.sh renders it into
|
||||||
# /home/dank/Containers/caddy/Caddyfile.
|
# /home/dank/Containers/caddy/Caddyfile, which the container mounts.
|
||||||
# CADDY_BASICAUTH_HASH: the shared family password, still used by the
|
# CADDY_BASICAUTH_HASH: the shared family password, now used only by the
|
||||||
# vhosts that carry basicauth rather than Authentik forward_auth
|
# pihole vhost (grafana moved behind the Authentik guard chain 2026-09-01).
|
||||||
# (grafana, pihole). Username: dankuser.
|
# Username: dankuser.
|
||||||
CADDY_BASICAUTH_HASH=changeme
|
CADDY_BASICAUTH_HASH=changeme
|
||||||
# (The homepage's per-user hashes were retired: the homepage and its /admin/
|
# (The homepage's per-user hashes were retired: the homepage and its /admin/
|
||||||
# page are now behind Authentik forward_auth, not basicauth.)
|
# page are now behind Authentik forward_auth, not basicauth.)
|
||||||
|
|||||||
+22
-13
@@ -22,15 +22,16 @@
|
|||||||
# CHALLENGE everyone else) → Caddy's internal listener http://:8016 (auth
|
# CHALLENGE everyone else) → Caddy's internal listener http://:8016 (auth
|
||||||
# decision; Host headers survive every hop) → authenticated traffic is
|
# decision; Host headers survive every hop) → authenticated traffic is
|
||||||
# forwarded back to http://:8017 and routed straight to the app.
|
# forwarded back to http://:8017 and routed straight to the app.
|
||||||
# Apps with their own auth (Grafana, Gitea, OpenWebUI, Jellyfin, *arr, Pi-hole)
|
# Apps with their own auth (Gitea, OpenWebUI, Jellyfin, *arr, Pi-hole) and the
|
||||||
# and the Authentik IdP itself (auth.franksdank.cloud — its login flow must never
|
# Authentik IdP itself (auth.franksdank.cloud — its login flow must never sit
|
||||||
# sit behind a challenge) are exempt by construction: their vhosts never route
|
# behind a challenge) are exempt by construction: their vhosts never route
|
||||||
# through Anubis. ComfyUI left this exempt set on 2026-08-31: it now sits behind
|
# through Anubis. ComfyUI left this exempt set on 2026-08-31 and Grafana left
|
||||||
# the guard chain with the comfyui-proxy provider registered on the embedded outpost.
|
# it on 2026-09-01 (auth_proxy mode; the outpost proxies authenticated traffic
|
||||||
# their vhosts never route through Anubis. The basicauth hash is a
|
# through to it): both now sit behind the guard chain with their proxy
|
||||||
# placeholder; deploy.sh renders the real hash (CADDY_BASICAUTH_HASH from the
|
# providers registered on the embedded outpost.
|
||||||
# host .env, git-ignored) into /home/dank/Containers/caddy/Caddyfile, which
|
# The pihole vhost keeps its basicauth edge; the hash placeholder below is
|
||||||
# the container mounts.
|
# rendered by deploy.sh from CADDY_BASICAUTH_HASH (host .env, git-ignored) into
|
||||||
|
# /home/dank/Containers/caddy/Caddyfile, which the container mounts.
|
||||||
#
|
#
|
||||||
# TLS: real Let's Encrypt certs. Site addresses carry no http:// prefix,
|
# TLS: real Let's Encrypt certs. Site addresses carry no http:// prefix,
|
||||||
# so Caddy serves HTTPS (and auto-redirects HTTP). Certs are issued via
|
# so Caddy serves HTTPS (and auto-redirects HTTP). Certs are issued via
|
||||||
@@ -132,12 +133,15 @@ gitea.franksdank.cloud {
|
|||||||
reverse_proxy 192.168.0.143:3000
|
reverse_proxy 192.168.0.143:3000
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Grafana ---
|
# --- Grafana (guarded: Anubis → Authentik; grafana-proxy provider, auth_proxy mode) ---
|
||||||
|
# Authenticated traffic returns at the internal :8017 listener and is proxied
|
||||||
|
# through by the outpost with Authorization: Bearer <client_id>_<client_secret>;
|
||||||
|
# Grafana's auth.proxy trusts that token and auto-upserts a user per login.
|
||||||
|
# The basicauth edge this replaces (CADDY_BASICAUTH_HASH) is retired.
|
||||||
grafana.franksdank.cloud {
|
grafana.franksdank.cloud {
|
||||||
basicauth {
|
reverse_proxy anubis:8923 {
|
||||||
dankuser REPLACE_WITH_HASH
|
header_up X-Real-Ip {remote_host}
|
||||||
}
|
}
|
||||||
reverse_proxy grafana:3000
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Prometheus ---
|
# --- Prometheus ---
|
||||||
@@ -302,6 +306,11 @@ http://:8017 {
|
|||||||
reverse_proxy loki:3100
|
reverse_proxy loki:3100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@grafana host grafana.franksdank.cloud
|
||||||
|
handle @grafana {
|
||||||
|
reverse_proxy grafana:3000
|
||||||
|
}
|
||||||
|
|
||||||
@prometheus host prometheus.franksdank.cloud
|
@prometheus host prometheus.franksdank.cloud
|
||||||
handle @prometheus {
|
handle @prometheus {
|
||||||
reverse_proxy prometheus:9090
|
reverse_proxy prometheus:9090
|
||||||
|
|||||||
@@ -177,8 +177,14 @@ services:
|
|||||||
user: "0:0"
|
user: "0:0"
|
||||||
environment:
|
environment:
|
||||||
GF_SERVER_ROOT_URL: "https://grafana.franksdank.cloud"
|
GF_SERVER_ROOT_URL: "https://grafana.franksdank.cloud"
|
||||||
GF_SECURITY_ADMIN_USER: "${GRAFANA_ADMIN_USER}"
|
# Auth proxy mode: the authentik embedded outpost proxies authenticated
|
||||||
GF_SECURITY_ADMIN_PASSWORD: "${GRAFANA_ADMIN_PASSWORD}"
|
# traffic through with Authorization: Bearer <client_id>_<client_secret>
|
||||||
|
# (the grafana-proxy provider on the outpost). The token lives in the
|
||||||
|
# host .env (never committed); auto-upsert maps each authenticated
|
||||||
|
# authentik user to a Grafana user by email, default role Viewer.
|
||||||
|
GF_AUTH_PROXY_ENABLED: "true"
|
||||||
|
GF_AUTH_PROXY_HEADERS: "name Auth;logo https://grafana.franksdank.cloud/public/img/login-app-logo.png;auto-upsert"
|
||||||
|
GF_AUTH_PROXY_TOKEN: "${GRAFANA_PROXY_TOKEN}"
|
||||||
ports:
|
ports:
|
||||||
- "3002:3000"
|
- "3002:3000"
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
Reference in new issue
Block a user