Skip to content

docs(identity): record the 6e forward-auth cutover as done - #409

Merged
PBernaerts merged 4 commits into
mainfrom
docs/6e-cutover-done
Aug 21, 2026
Merged

docs(identity): record the 6e forward-auth cutover as done#409
PBernaerts merged 4 commits into
mainfrom
docs/6e-cutover-done

Conversation

@PBernaerts

Copy link
Copy Markdown
Owner

All three forward-auth gates moved to authentik on 2026-08-21: music, then
MTG, then the apex, one deploy.yml --tags site_config render each, with the
user present and every gate proven before the next was touched.

Docs only. The gate variables themselves live in the untracked host
site.yml, so nothing here changes behaviour.

What was proven live

check result
all three gates redirect to login.<domain>
/beheer/ with a forged Remote-Groups: grafana-admins login redirect, not the admin page ✅
ordinary member (media-users, no operator group) on /beheer/ 403 ✅
operator on /beheer/ 200 ✅
non-media account on the apex denied ✅
/assets/brand/favicon-badge.png, no session 200 ✅
/assets/art/ still gated ✅
/rest/ping on music 200, portal skipped ✅
www still a plain 301 ✅
/outpost.goauthentik.io/ping on each gated host 204 ✅
Gatus 15/15 green across the cutover, config self-reloaded ✅

Caddy was reloaded, never restarted, so no proxy-outpost session was dropped.

Also in here

  • The account and password-reset links moved to authentik during the sitting
    (/if/user/#/settings and the corsarium-recovery flow), so they come off
    the 6f sweep list. Gatus's "Inloggen (account)" endpoint follows the same
    variable and keeps its key, so its history survives.
  • Two things found and deliberately not fixed here, both queued: authentik's
    authorization-denied page is still in English (a 6t follow-up, member-reachable
    but not a blocker), and the operator's beheer tile still links at Authelia
    (added to the 6f sweep list).
  • site.yml.example keeps authelia on all three gates on purpose. The offline
    render in tests/run.sh reads that file directly, and "no gate variables set
    renders Authelia" is the assertion that makes the rollback safe.

tests/run.sh is green.

All three gates moved to authentik on 2026-08-21, music then MTG then the
apex, one `--tags site_config` render each, every gate proven before the
next was touched. Authelia is still running and still holds its rules, so
the rollback is still one line per gate.

Records what the sitting taught rather than just that it happened:

- a `curl` to /beheer/ carrying a forged `Remote-Groups` gets the login
  redirect, because the header strips run before forward-auth, which runs
  before the operator matcher. The strip count going 4 to 12 is the cheap
  check that the strips are there at all.
- proving the operator rule in both directions needs a member who is in
  media-users and not in the operator group. A groupless account cannot do
  it, because the apex refuses it before it reaches the matcher.
- private windows share one jar until the last one closes, which twice made
  a working gate look like it was not gating. A stateless curl settles it.

Also queues two things found on the way and deliberately left alone:
authentik's authorization-denied page is still English, and the operator's
beheer tile still links at Authelia. The account and reset links moved to
authentik as part of the sitting, so they come off the 6f sweep list.
Item 2 was proven by the sitting itself and item 7 has its first positive:
a real member authorized the Muziek proxy application minutes after that
gate flipped, which is an event that cannot exist unless the gate had
already moved.

Two traps worth having written down before the rest of the list runs:

- item 5 splits, and only the delivery half is cheap. A GET on the alert
  webhook answers 200 with the script's User-Agent and 403 with urllib's
  default, reproducing #401 exactly, and an alert composed through the
  script's own Notifier was delivered and seen. Proving delivery first is
  what makes a later silent trigger diagnosable instead of ambiguous.
- item 3 is easy to fake. A desktop client on the LAN reaches Navidrome
  directly and never touches Caddy, so it says nothing about the gate.
  Navidrome's proxy-ip is the tell, and the "IP is not whitelisted"
  warning on a direct connection is correct behaviour, not a regression.
Amperfy on iOS over mobile data, through the public hostname, registered as
a player. That is the /rest bypass in the flipped gate doing its job.

Both near-misses are written down, because each one looks like the other
thing. A desktop client on the LAN never touches Caddy, so it proves
nothing while looking like a pass. And once the request does arrive, a
rejected login looks like a gate fault and is not one: /rest authenticates
against Navidrome's own credential, so the portal password is the wrong
one to type and MFA is not in that path at all. The log separates them
before any theorising: a public remoteAddr on /rest/ping.view already
proves the gate let it through.
#412 landed the 6f evidence records for items 2, 3 and 7 while this branch was
open, and #413 landed the 6f-pre sweep, so both sides had touched the same two
regions.

Status table: each side owned one row, so both were kept. 6e is DONE per this
branch, 6f-pre is DONE per #413.

Evidence section: kept main's "Three things the 2026-08-21 run turned up" and
dropped this branch's progress table, which had gone stale. It still listed
items 1 and 5 as owed and both were proven by #411, and items 2, 3 and 7 are now
recorded properly by #412, so the table would have contradicted the section
directly above it.

Kept the two traps this branch found, because neither is anywhere else: item 5
splitting into a cheap delivery half and an expensive trigger half, and item 3
being easy to fake with a LAN client that never touches Caddy at all.
@PBernaerts
PBernaerts merged commit 64e2669 into main Aug 21, 2026
9 checks passed
@PBernaerts
PBernaerts deleted the docs/6e-cutover-done branch August 21, 2026 11:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant