echo6-docs/docs/software/authentik.md
Matt Johnson e9231ac24a Migration: consolidate Echo6 docs to cortex with full infrastructure cleanup sync
- Documents recent infrastructure cleanup (8 CTs destroyed, 35 DNS records removed, Headscale cleanup)
- Adds 24 new runbooks covering Authentik, PeerTube, Meshtastic, RECON, Proxmox, Mailcow, Internet Archive, GPU routing
- Adds project documentation for headscale, vaultwarden, peertube, matrix, mmud, advbbs, arr stack
- Updates services.md, environment.md, caddy.md, authentik.md to match live infrastructure
- Removes 4 deprecated runbook duplicates (canonical versions live in projects/)
- Adds .gitignore for binary archives and editor temp files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 06:02:16 +00:00

14 KiB

Authentik SSO Configuration

Location

API Access

API token stored in /home/zvx/projects/.ref/credentials as AUTHENTIK_API_TOKEN

# Test API access
curl -s "https://auth.echo6.co/api/v3/core/applications/" \
  -H "Authorization: Bearer $AUTHENTIK_API_TOKEN" | python3 -m json.tool

Flow UUIDs

Required for OAuth2 provider creation:

Flow UUID
Authorization (implicit) 86051292-389f-4bd9-b0f9-53cd32f197fd
Authorization (explicit) 6f9f5c89-9f98-4776-9e0d-a72a8ad17963
Invalidation ed861c0d-2c81-4c3d-819b-946a21c4296a
Provider Invalidation 1eb91626-19a3-4f45-b384-d699c6189197

Signing Key

Key UUID
authentik Self-signed Certificate 09f508f0-6b8e-4031-8563-0d3cebf86868

Property Mappings (Standard OIDC Set)

Include these three in every provider:

Mapping UUID
OpenID Connect scope: openid c6426dad-0d85-4daa-89fe-cb850ad4bfd7
Echo6 OAuth: email (verified=true) 02c22323-da89-457a-bc12-7f4dd6a3d8ab
OpenID Connect scope: profile 113ab791-fa04-4e8c-b103-09d706bc21b4

Note: The default email scope (096b0d6f) was changed in 2025.10 to return email_verified: false. Our custom scope (02c22323) overrides this to always return true. All 14 OAuth2 providers were migrated to use the custom scope on 2026-02-16.

Current OAuth2 Providers

PK Name Client ID Application Redirect URI
1 Mailcow mailcow Mailcow https://mail.echo6.co/sso/oidc
2 Forgejo forgejo Forgejo https://forge.echo6.co/user/oauth2/Authentik/callback
3 Vaultwarden vaultwarden Vaultwarden https://vault.echo6.co/identity/connect/callback
4 Proxmox proxmox Proxmox VE https://proxmox.echo6.co (regex)
5 Headscale headscale Headscale VPN https://vpn.echo6.co/oidc/callback
6 Headplane headplane Headplane https://vpn.echo6.co/admin/oidc/callback
8 Nextcloud nextcloud Nextcloud https://nextcloud.echo6.co/apps/oidc_login/oidc
9 Immich immich Immich https://immich.echo6.co/auth/login, /api/oauth/mobile-redirect
10 jellyfin jellyfin Jellyfin https://jellyfin.echo6.co/sso/OID/redirect/Authentik
11 jellyseer jellyseer Jellyseer https://requests.echo6.co/(login|api/v1/auth/oidc-callback).* (regex)
12 PeerTube peertube PeerTube https://stream.echo6.co/plugins/auth-openid-connect/...
13 WATCHTOWER watchtower WATCHTOWER Forward auth (proxy provider)
14 Open WebUI open-webui Open WebUI https://ai.echo6.co/oauth/oidc/callback
15 Matrix 93kCoZkBlnJyD9EcAm7E4btKflecOcBm9DGONB5T Matrix https://matrix.echo6.co/_synapse/client/oidc/callback
16 Files Forward Auth Files Forward auth (proxy provider)
17 LiveSync Provisioner ZBoLdYmxlSUyMqgekswIPS4YuaeBn5uCr8GtWm5H LiveSync Forward auth (proxy provider)

Groups

| Name | PK | Superuser | Members | Used By | |------|----|-----------|---------|----- ---| | authentik Admins | 9944e153-f860-4443-81d1-ae544f611806 | Yes | akadmin, matt | All apps (admin access) | | media-users | 0820b2b8-6c54-4c20-9a0a-872820e6d9ea | No | jodie, matt | Jellyfin, Jellyseer, PeerTube | | ai-users | 0631b273-cfd8-4ed1-afa6-e262d0dc5a69 | No | matt | Open WebUI | | cloud-users | db3cbf5d-8057-4e33-8e8d-95bfdb35fbac | No | — | Immich, Nextcloud | | communication-users | 31bce176-cd86-4aea-8db3-a57e03d5c2d1 | No | — | Mailcow, Matrix | | productivity-users | 698d80c7-7c29-43cd-b5d4-9eb24c85a6cc | No | — | — | | security-users | f345a043-c2a4-4906-a43b-9860eae86ee1 | No | — | — | | proxmox_admins | d85a868d-7d1e-4585-92a8-b8bb86771b53 | No | akadmin, matt | Proxmox VE | | proxmox_users | cf26703a-a824-47dd-9550-30b848a8ce5f | No | — | Proxmox VE | | authentik Read-only | ce03664b-46f3-43b7-9967-5f65d591fdb6 | No | — | RBAC read-only role | | livesync-users | 8e575a86-326e-4df8-8828-8379d8ab861f | No | matt | LiveSync |

Application Access Pattern

Every application uses policy_engine_mode: "any" with two group bindings:

  1. authentik Admins — gives admin/superuser access to all apps
  2. Service-specific group — controls which regular users can access the app

Users must be in at least one bound group to access the application.

Create New API Token

ssh root@100.64.0.1 'docker exec -i authentik-server ak shell' <<'PYEOF'
from authentik.core.models import Token, TokenIntents, User
user = User.objects.get(username="akadmin")
Token.objects.filter(identifier="token-name").delete()
t = Token(identifier="token-name", user=user, intent=TokenIntents.INTENT_API, expiring=False, managed=None)
t.save()
print(t.key)
PYEOF

Full OAuth2 App Setup (Provider + Application + Group + Bindings)

Step 1: Create the OAuth2 provider

curl -s -X POST "https://auth.echo6.co/api/v3/providers/oauth2/" \
  -H "Authorization: Bearer $AUTHENTIK_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "AppName",
    "authorization_flow": "86051292-389f-4bd9-b0f9-53cd32f197fd",
    "invalidation_flow": "ed861c0d-2c81-4c3d-819b-946a21c4296a",
    "property_mappings": [
      "c6426dad-0d85-4daa-89fe-cb850ad4bfd7",
      "02c22323-da89-457a-bc12-7f4dd6a3d8ab",
      "113ab791-fa04-4e8c-b103-09d706bc21b4"
    ],
    "client_type": "confidential",
    "client_id": "appname",
    "client_secret": "<generate-a-long-random-secret>",
    "redirect_uris": [{"matching_mode": "strict", "url": "https://app.echo6.co/callback"}],
    "sub_mode": "user_username",
    "signing_key": "09f508f0-6b8e-4031-8563-0d3cebf86868",
    "include_claims_in_id_token": true
  }'
# Note the "pk" from the response — needed for Step 2

Step 2: Create the application

curl -s -X POST "https://auth.echo6.co/api/v3/core/applications/" \
  -H "Authorization: Bearer $AUTHENTIK_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "AppName",
    "slug": "appname",
    "provider": PROVIDER_PK,
    "meta_launch_url": "https://app.echo6.co",
    "policy_engine_mode": "any"
  }'
# Note the "pk" from the response — needed for Step 4

Step 3: Create the user group

curl -s -X POST "https://auth.echo6.co/api/v3/core/groups/" \
  -H "Authorization: Bearer $AUTHENTIK_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "appname-users",
    "is_superuser": false,
    "users": [7]
  }'
# user 7 = matt. Note the "pk" from the response.

Step 4: Bind groups to the application

# Bind authentik Admins
curl -s -X POST "https://auth.echo6.co/api/v3/policies/bindings/" \
  -H "Authorization: Bearer $AUTHENTIK_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "target": "APPLICATION_PK",
    "group": "9944e153-f860-4443-81d1-ae544f611806",
    "order": 0, "enabled": true, "negate": false, "timeout": 30
  }'

# Bind service-specific group
curl -s -X POST "https://auth.echo6.co/api/v3/policies/bindings/" \
  -H "Authorization: Bearer $AUTHENTIK_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "target": "APPLICATION_PK",
    "group": "GROUP_PK",
    "order": 0, "enabled": true, "negate": false, "timeout": 30
  }'

Step 5: Verify

# OIDC discovery should return endpoints
curl -s "https://auth.echo6.co/application/o/appname/.well-known/openid-configuration" | python3 -m json.tool

# Check bindings
curl -s "https://auth.echo6.co/api/v3/policies/bindings/?target=APPLICATION_PK" \
  -H "Authorization: Bearer $AUTHENTIK_API_TOKEN"

Common Redirect URI Patterns

Application Type Redirect URI Pattern
Web app (generic) https://app.echo6.co/callback
Web app (oauth path) https://app.echo6.co/oauth/callback
Open WebUI (OIDC) https://app.echo6.co/oauth/oidc/callback
Forgejo https://app.echo6.co/user/oauth2/Authentik/callback
Jellyfin (SSO plugin) https://app.echo6.co/sso/OID/redirect/Authentik
Caddy forward auth https://app.echo6.co/outpost.goauthentik.io/callback

Users

PK Username Name Email
6 akadmin authentik Default Admin root@example.com
7 matt Matt Johnson matt@echo6.co
9 jodie Jodie johnsonsinidaho@gmail.com

Email Invitation System

SMTP Configuration

Authentik sends email via Mailcow:

Setting Value
SMTP Host mail.echo6.co
SMTP Port 587 (STARTTLS)
Username no-reply@echo6.co
From no-reply@echo6.co

Important: The no-reply@echo6.co mailbox MUST have authsource=mailcow in the Mailcow database (not generic-oidc). If it gets reset to generic-oidc, SMTP auth will fail because Dovecot tries to authenticate via Authentik SSO instead of the local password. Fix with:

docker exec mailcowdockerized-mysql-mailcow-1 mysql -u mailcow -p<DBPASS> mailcow \
  -e "UPDATE mailbox SET authsource='mailcow' WHERE username='no-reply@echo6.co'"

Enrollment Flow

Component PK
Flow (invitation-enrollment) 184a9e20-f5c5-4b44-8775-266a568439c0
Invitation stage (enrollment-invitation) 994252a6-a659-4304-b9aa-a6591857a53b
Prompt stage (enrollment-credentials) a5e2a2f1-95c9-4627-a3dd-e0915ff64cda
User write stage (enrollment-user-write) 05f565e0-9d64-4ecc-b738-8ffc697ad829
User login stage (enrollment-user-login) f23958ea-47bd-4fb2-a657-b6f85fc6331a

Stage order: Invitation (10) → Prompt (20) → User Write (30) → User Login (40)

Flow settings: authentication=require_unauthenticated, continue_flow_without_invitation=false

User write creates users under users/enrolled path.

Email Automation

Uses the community pattern from authentik/discussions/13305:

Component PK
Expression policy (invitation-email-sender) 770188de-2b60-4e87-820a-fa64d419ed89
Notification rule (invitation-email-trigger) a145a8c9-b3eb-440d-8b77-27139c346a17

When an invitation is created with an email field in custom attributes, the expression policy triggers ak_send_email() to send the enrollment link to the invitee automatically.

How to Use

Invite via email (Admin UI → Directory → Invitations → Create):

  1. Name it, select Invitation Enrollment flow, toggle Single use on, set expiry
  2. Custom attributes:
    name: Jane Smith
    email: jane@example.com
    
  3. Click Create — email is sent automatically

Invite via link (no email):

  1. Same as above but leave custom attributes empty (or omit email field)
  2. Click Create → expand the row → copy the invitation link
  3. Send the link manually

Branding & Theming

Echo6 cyberpunk branding applied to Authentik 2025.12.4 via System → Brands.

Brand Settings

Setting Value
Brand title echo6
Theme dark (forced, not automatic)
Logo /media/custom/echo6-logo.png (uploaded via Customization → Files)
Favicon /media/custom/echo6-favicon.png (uploaded via Customization → Files)
Custom CSS Echo6 Authentik CSS (~200 rules, applied via Brand → Custom CSS field)

Flow Titles

Flow Title
Authentication echo6 // login
Invalidation echo6 // logout
Recovery echo6 // recovery
User Settings echo6 // settings

Custom CSS Highlights

  • Font: JetBrains Mono globally (with :not() exclusions for FontAwesome/PatternFly icon fonts)
  • Colors: Cyan #28C0E8 primary accent, Yellow #F0D848 secondary, dark backgrounds #0a0e17/#111827/#1a2332
  • Login card: Dark background, cyan-glow focus on inputs, branded submit button
  • Admin sidebar: Dark with cyan hover/active states
  • User dashboard: 3-column grid layout, dark cards with cyan border on hover
  • Application icons: Custom SVG icons uploaded for all 15 services

CSS Storage

The custom CSS is stored in the Brand model's branding_custom_css field. To update:

# Copy CSS to Contabo
scp /path/to/echo6-authentik.css root@100.64.0.1:/opt/authentik/branding/custom.css

# Load into Brand model via ak shell
ssh root@100.64.0.1 'docker exec -i authentik-server ak shell' <<'PYEOF'
from authentik.brands.models import Brand
b = Brand.objects.get(domain="auth.echo6.co")
b.branding_custom_css = open("/media/custom/custom.css").read()
b.save()
PYEOF

# Restart to apply
ssh root@100.64.0.1 'cd /opt/authentik && docker compose restart server worker'

SSO Launch URL Pattern

All authenticated service links use Authentik's application launch URL:

https://auth.echo6.co/application/launch/<app-slug>/

This provides seamless SSO: authenticated users pass through to the app, unauthenticated users get the login page then redirect to the app. Used by the SearXNG waffle menu and nav bar.

App Slug Service Launch URL
open-webui Aurora (AI) https://auth.echo6.co/application/launch/open-webui/
peertube Stream https://auth.echo6.co/application/launch/peertube/
files Files https://auth.echo6.co/application/launch/files/
watchtower Watchtower https://auth.echo6.co/application/launch/watchtower/
immich Photos https://auth.echo6.co/application/launch/immich/
mailcow Mail https://auth.echo6.co/application/launch/mailcow/
nextcloud Cloud https://auth.echo6.co/application/launch/nextcloud/
jellyfin Jellyfin https://auth.echo6.co/application/launch/jellyfin/
jellyseer Requests https://auth.echo6.co/application/launch/jellyseer/

Brand Color Reference

Color Hex Usage
Cyan #28C0E8 Primary accent, links, focus states
Cyan Light #5DD4F5 Hover states
Yellow #F0D848 Secondary accent, badges
BG Primary #0a0e17 Page backgrounds
BG Secondary #111827 Cards, inputs
BG Tertiary #1a2332 Elevated surfaces
Border #1e3a5f All borders
Text Primary #e0e6ed Main text
Text Muted #7a8ca0 Secondary text

Last updated: 2026-02-18 — Added LiveSync proxy provider (PK 17) + livesync-users group, Files Forward Auth (PK 16). Authentik 2025.12.4