6 Commits
Author SHA1 Message Date
Frank f134cc8876 docs+units: fix every claim my own changes made false
Retiring dankclaw/compose.yaml and adding alert rules invalidated claims across
the repo, including in the rule file agents read first. Clean cutover includes
the prose.

**Tests that had gone hollow.** Four assertions grepped dankclaw/compose.yaml
for a service name. With the file gone they passed by *absence* — a gate that
can no longer fail. Each now asserts the real invariant ("no dankclaw compose
file competes with the quadlet units") and keeps a live check for a re-added
entry, so it still fails when one appears: verified by recreating a compose file
with a comfyui service and watching three tests go red, then removing it.

**AGENTS.md, which was wrong about ComfyUI.** It said ComfyUI runs CPU-only
("no ROCm wheels for gfx1151, CUDA images wrong"). That was true in the
compose era and is false now: the restored unit runs with /dev/kfd + /dev/dri and
must NOT pass --cpu. An agent trusting the rule file would have re-broken it.
Also corrected: the observability paragraph ("RUNNING BUT UNCONFIGURED, no
datasource, no rules" — all three have been configured since 2026-09-16), the
Active runbook row that still named halogen for frank-large, halogen's absence
from the Retired table, the benchmark policy naming halogen's harness, and the
seam list.

**Unit and page claims.** prometheus.container said "no alerting rules anywhere
in this stack"; node-exporter.container said Dankserver runs from its compose
stack; Prometheus.md documented three jobs as working (they scrape HTML: they
can never report up) and said no dashboard existed; index.md and the three
authentik service pages pointed at the retired file; Authentik.md's upgrade
instruction told you to bump an image tag in it.

One bad edit of my own on the way (a stale line number clobbered a See Also
entry in Prometheus.md) — caught by reading back, fixed, and the vault link
checker now proves the cross-references hold.
2026-09-16 07:46:23 -07:00
Frank 29f9a86884 caddy+authentik tests: uniform Host-preserving :8016 proxy through embedded outpost
The redirect-to-flow design with an absolute cross-host next= was rejected by
the flow's open-redirect guard at completion ("Request has been denied:
Invalid next URL"), and meta-header routing does not exist in this build
(providers route on the ORIGINAL Host). :8016 now proxies every request whole
to authentik-server:9000 preserving Host; the embedded outpost serves login
in place and forwards authenticated traffic back to :8017. Requires one proxy
provider per guarded host (provisioned live: search/hermes/prometheus/romm/
files + www, flows backfilled). Tests flipped from the meta-header claim to
the upheld contract: Host preserved, no absolute next= redirects.
2026-08-29 23:49:39 -07:00
Frank 8898740ca4 caddy: www holds the homepage; naked domain redirects at the TLS edge
The proxy provider matches external_host exactly, so Host=www matched zero
providers and Authentik answered its error page while the naked domain
served the homepage. Flip the topology: www.franksdank.cloud is the one
guarded vhost carrying the homepage through Anubis -> Authentik -> :8017;
franksdank.cloud (plus legacy names and the bare-IP catch-all) 308-redirects
onto www before any challenge. Tests flipped to assert the new contract.
2026-08-29 15:11:18 -07:00
Frank ef07e7d01a fix(caddy,authentik): auth guarded vhosts by proxying the whole request through authentik
The forward_auth target /outpost.goauthentik.io/auth/caddy does not exist
in authentik 2026.8 (verified live: 404 for every header combination; the
URL tree has no outpost auth prefix at all — the outpost worker dials back
to core over ws/outpost/<uuid>/ instead). Unauthenticated subrequests got
404, Caddy treated >=400 as 'not authenticated' and redirected browsers to
the dead path — users saw authentik's own Not-Found page.

Fix: guarded vhosts now proxy the whole request through authentik-server:9000
with X-authentik-meta-outpost/-provider/-app headers (the exact header set
this build's Traefik controller emits, adapted for Caddy). Unauthenticated
clients get the login flow served in place; once a session exists,
authentik proxies on to the provider's internal_host — now
http://caddy:8017, a new post-auth internal listener that routes straight to
the app. The chain terminates; nothing dials back into authentik.

Live DB changes applied alongside (postgres is the source of truth):
provider pk=1 authentication_flow=default-authentication-flow (was NULL —
the actual cause of the 404s) and internal_host=http://caddy:8017 (was
self-referential http://authentik-server:9000).
2026-08-28 22:28:32 -07:00
Frank 914e251ebc authentik: boot-persistent quadlet conversion with deploy handler
The compose-era authentik trio died at every boot (rootless podman does not
auto-start bare containers). Convert the trio to Quadlet units installed by
deploy-remote.sh into ~/.config/containers/systemd/, enabled + WantedBy=
default.target:

- 3 unit files under dankclaw/authentik/quadlet/ (postgres -> server -> worker
  ordering via Wants=/After=; secrets stay in the git-ignored host .env,
  expanded by systemd at start time exactly like the gitea units)
- deploy_authentik() handler: install units, daemon-reload, retire stale
  compose-era containers only while units are inactive, enable once, then
  start in dependency order with podman-health gates between stages
- compose.yaml: authentik service definitions retired to a comment pointing at
  the quadlet dir (same pattern as searxng/open-webui/gitea/caddy)
- tests/authentik.bats rewritten from compose assertions to unit-file
  contract assertions (images, Exec roles, ordering, loopback-only publish,
  pg_isready probe, secret hygiene, dispatch routing)
2026-08-28 03:09:19 -07:00
Frank 3cc99d81cc Authentik SSO + homepage naked domain
Auth layer (Authentik 2026.8.0):
- compose: 3-service stack (authentik-postgres, authentik-server, authentik-worker),
  postgres health-gated, bind mounts under /home/dank/authentik
- Caddyfile: auth.franksdank.cloud vhost; forward_auth on the no-auth vhosts
  (homepage, SearXNG, Hermes, Prometheus, RomM, Copyparty); outpost path
  proxied first in a route block
- .env.example: AUTHENTIK_PG_PASS + AUTHENTIK_SECRET_KEY
- deploy.sh: render only CADDY_BASICAUTH_HASH (the homepage per-user hashes
  are retired; grafana + pihole keep basicauth)
- tests/authentik.bats (new) + updated homepage/caddyfile/pihole seams
- docs: Authentik.md + per-service pages; Caddy.md + Homepage.md updated

Homepage (naked domain):
- Caddyfile: dankclaw.franksdank.cloud -> franksdank.cloud www.franksdank.cloud;
  dankclaw + dankserver redirect to it; bare-IP catch-all updated
- addn-hosts: A records for the naked domain, www, and auth (all -> 143)
- tests/pihole.bats: vhost_names handles multi-address blocks; TLD check
  allows the naked domain

All 146 tests pass.
2026-08-24 23:48:27 -07:00