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:
@@ -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
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user