Token exchange chain verified end-to-end in-process on the live provider (pk 9): authorize -> ORM-minted code -> form-encoded token exchange with Basic client auth -> userinfo. Key findings documented: - Application row + grant_types must exist before authorize can complete - token endpoint consumes form-encoded bodies only (JSON body => no grant_type parsed -> unsupported_grant_type); client auth is Basic-only - PropertyMappingEvaluator.evaluate(*args,**kwargs) forwards kwargs to BaseEvaluator.evaluate(expression_source), so context kwargs become the expression source and every evaluation raises a swallowed exception; userinfo therefore answers sub-only claims for every provider in this fork. Scope granting filter (provider= M2M descriptor) is always empty. - Grafana identity = sub hash until the evaluator bug is fixed upstream.
2.3 KiB
2.3 KiB
Grafana
Grafana visualizes the metrics that Prometheus collects from every service. It runs on Dankclaw and is reachable at grafana.franksdank.cloud (via Caddy, behind the Anubis challenge + embedded-outpost gate; login happens inside Grafana via the Authentik OAuth2 button).
Host: Dankclaw — Hostname: grafana.franksdank.cloud — Port: 3002 (internal) — Docs: https://grafana.com/docs
Facts
| Item | Value |
|---|---|
| Image | docker.io/grafana/grafana:latest |
| Port | 3002 (host) → 3000 (container) |
| Data volume | dashboards, users, datasource config |
| Datasource | Prometheus (on the same host) |
| Provisioning | dashboards in /etc/grafana/provisioning/dashboards |
Configuration
environment:
GF_SECURITY_ADMIN_USER: "${GRAFANA_ADMIN_USER}"
GF_SECURITY_ADMIN_PASSWORD: "${GRAFANA_ADMIN_PASSWORD}"
GF_SERVER_ROOT_URL: "https://grafana.franksdank.cloud"
volumes:
- /opt/grafana/data:/var/lib/grafana
- /opt/grafana/provisioning:/etc/grafana/provisioning:ro
Datasource
Point Grafana at the Prometheus service by name (http://prometheus:9090) on the shared podman network.
Healthcheck
Grafana responds on /api/health with 200 and "database":"ok".
Gotchas
- Change the default admin credentials at first boot (env or UI).
- Dashboards provisioned as YAML survive container recreation; UI-created ones live in the data volume — back it up.
- Auth = OAuth2 relying-party, not auth_proxy. The embedded outpost carries
no provider token (
token=None), so no identity header ever reaches Grafana; RP mode is topology-independent. The full verified contract (provider pk 9, client_idgrafana-21ca190cde75d60f, global authorize/token/userinfo paths, Basic client auth, form-encoded token body, and the fork's userinfo-claims bug that leaves identity at thesubhash only) is in Authentik → "OAuth2 relying-party quirks". Consequences for Grafana: users auto-upsert as Viewer withlogin = <sub hex>; no email/groups/role claims reach Grafana until the evaluator bug is fixed — do not write role mappings that depend on those claims. The local admin account stays the only Admin.
See Also
- Dankclaw Stack
- Prometheus — the datasource
- Observability — the whole stack