docs: authentik/anubis/network corrected to live-verified outpost behavior

Meta-header routing and forward_auth removed from the described design — both
disproved live. Documents: Host-based provider routing with per-guarded-host
proxy providers (lockstep rule), the null-flows wedge that starves the
embedded outpost config fetch, the Anubis /outpost.goauthentik.io/* transport
exemption, the single-file bind-mount stale-policy inode gotcha, Invalid next
URL as a dead design, and the public-DNS record requirement per guarded host.
This commit is contained in:
Frank
2026-08-29 23:55:48 -07:00
parent 2a72efad44
commit ee1e038f30
3 changed files with 116 additions and 69 deletions
+24 -9
View File
@@ -4,9 +4,8 @@ Anubis is the bot-challenge proxy that fronts the guarded public vhosts on
Dankclaw. Browsers get a proof-of-work challenge; AI scraper user-agents are
denied outright. It sits in a two-tier chain: client → Caddy TLS listener →
Anubis (`:8923`, internal-only) → Caddy internal listener (`:8016`) → app.
Host headers survive both hops, so per-vhost routing (and Authentik
`forward_auth` for the wrapped apps) resumes unchanged behind it. See
[[Caddy]] and [[Authentik]].
Host headers survive both hops, so the Authentik embedded outpost can route
on the original `Host` behind it. See [[Caddy]] and [[Authentik]].
```mermaid
graph LR
@@ -14,7 +13,7 @@ graph LR
T --> A[Anubis verify :8923]
A -->|accepted| I[Caddy internal listener :8016]
A -->|challenge or deny| C
I --> P[per-vhost routing and forward_auth]
I --> P[whole-request proxy to Authentik outpost]
```
## Facts (live inventory)
@@ -31,10 +30,14 @@ graph LR
Policy content: an `ALLOW` rule for Anubis's own endpoints (the
`/.within.website/x/cmd/anubis/*` API and static namespace — the challenge
JS calls `make-challenge`/`pass-challenge` under that prefix, and challenging
those endpoints makes the challenge challenge itself), then DENY for
AI-scraper user-agent regexes (GPTBot, Claude-*, Perplexity*, CCBot,
Bytespider, Amazonbot, meta-externalagent, and friends), then CHALLENGE for
everything else (`path_regex: "."` catch-all). DNSBL off. Valid action verbs
those endpoints makes the challenge challenge itself), an `ALLOW` rule for
the Authentik transport prefix `^/outpost\.goauthentik\.io/` (login, start,
callback and the outpost's static assets must be reachable before any
session or challenge dance completes — authentik's own session gate protects
them), then DENY for AI-scraper user-agent regexes (GPTBot, Claude-*,
Perplexity*, CCBot, Bytespider, Amazonbot, meta-externalagent, and friends),
then CHALLENGE for everything else (`path_regex: "."` catch-all). DNSBL off.
Valid action verbs
at this tag are `ALLOW`, `CHALLENGE`, `DENY` — `ACCEPT` is not one of them
(first deploy of that rule crash-looped the unit on exactly that typo;
verified against the image binary's string table). The policy schema at this
@@ -49,7 +52,7 @@ These never route through Anubis (no policy bypass rule needed): plex
ungated), and gitea (git smart-HTTP clients cannot solve JS challenges —
`/info/refs` and `git-*-pack` paths pass unchallenged).
## Gotchas (all verified live 2026-08-28)
## Gotchas (all verified live; 1–6 on 2026-08-28, 7 on 2026-08-30)
1. **Image ref casing.** Podman's reference parser rejects mixed-case
repository refs before any network I/O (`repository name must be
@@ -87,6 +90,16 @@ ungated), and gitea (git smart-HTTP clients cannot solve JS challenges —
login flow. Verify with a JS-capable client end-to-end — mint via
`make-challenge`, solve, submit with browser-exact query params — before
declaring a challenge chain healthy.
7. **Single-file bind mount + git pull = stale policy.** The policy is
mounted file-at-a-time (`/home/dank/serverAppConfigs/dankclaw/anubis/
policy.json:/policy/policy.json:ro`); bind mounts pin the INODE. A
`git pull`/checkout that replaces the file leaves the running container
reading the old inode indefinitely (observed live: 22 h of uptime serving
a policy already superseded on disk, with no reload log line because
there is nothing watching). A policy change only takes effect when the
anubis container is (re)started — `./scripts/deploy.sh dankclaw
--service anubis` — and the deployer must therefore always restart it
rather than trust the file contents on disk.
## Verify live
@@ -94,4 +107,6 @@ ungated), and gitea (git smart-HTTP clients cannot solve JS challenges —
ssh dankclaw 'systemctl --user is-active anubis.service'
curl -s -o /dev/null -w "%{http_code}\n" -A "GPTBot" https://franksdank.cloud/ # denied page
curl -s -o /dev/null -w "%{http_code}\n" -A "Mozilla/5.0" https://franksdank.cloud/ # challenge 200
curl -s https://search.franksdank.cloud/outpost.goauthentik.io/login | grep -q Making\ sure && echo BROKEN-still-challenged || echo outpost-transport-exempt
```