blumeops/docs/reference/services/authentik.md

91 lines
3.6 KiB
Markdown
Raw Normal View History

---
title: Authentik
Doc review: 5 stalest cards; scale back ai-docs rule; document heph CLI (#373) ## Doc review (5 stalest, all never-reviewed) Each card was verified against live state (ArgoCD app list/health, manifests, 1Password item fields, Mealie API probe) and stamped `last-reviewed: 2026-06-09`. | Card | Findings fixed | |------|----------------| | `reference/services/argocd.md` | Added Authentik SSO (public PKCE client, `--sso` login, admins→role:admin RBAC); documented dual-cluster management (minikube + ringtail k3s at `ringtail.tail8d86e.ts.net:6443`); corrected sync policy — the `apps` root is **manual**, not automated | | `reference/services/authentik.md` | Blueprint list grown from 5 to 10 files; OIDC client table now lists all 8 clients with types; secrets table updated to `postgresql-*` fields and per-client secrets | | `reference/services/grafana.md` | TeslaMate datasource moved to `pg.ops.eblu.me:5434` (ringtail); dashboard inventory refreshed (20 provisioned ConfigMaps); TeslaMate dashboards documented as init-container fetch from forge mirror at pinned tag; SSO role mapping wording corrected (Admin only for `admins` group) | | `reference/infrastructure/unifi.md` | UnPoller image is now locally built (`registry.ops.eblu.me/blumeops/unpoller`); verified namespace/port | | `how-to/mealie/plan-a-meal.md` | Procedure verified; **found the stored API token (`op://blumeops/mealie/credential`) returns 401** — operational fix in progress, doc content unchanged | ## AGENTS.md - **Scaled back the ai-docs rule** (per discussion): agents now start by finding and reading relevant docs; `mise run ai-docs` (~130K tokens now) and `ai-sources` become opt-in bulk loads. `agent-change-process.md` updated to match. The `ai-docs` mise task itself is kept for now — happy to retire it in a follow-up if desired. - **Documented the heph CLI** task workflow (list/show/context/log read paths; done/drop/skip/log/edit/task write paths) so future sessions can read and manipulate Blumeops tasks without rediscovery. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.eblu.me/eblume/blumeops/pulls/373
2026-06-09 16:05:01 -07:00
modified: 2026-06-09
last-reviewed: 2026-06-09
tags:
- service
- security
- oidc
---
# Authentik
OIDC identity provider for BlumeOps. Authentik is the **source of truth** for user identity — users are created and managed in Authentik, and services authenticate against it via OIDC.
## Quick Reference
| Property | Value |
|----------|-------|
| **URL** | https://authentik.ops.eblu.me |
| **Admin UI** | https://authentik.ops.eblu.me/if/admin/ |
| **Tailscale URL** | https://authentik.tail8d86e.ts.net |
| **Namespace** | `authentik` |
| **Cluster** | k3s (ringtail) |
| **Manifests** | `argocd/manifests/authentik/` |
| **Container build** | `containers/authentik/default.nix` |
## Architecture
Authentik runs on [[ringtail]]'s k3s cluster, isolated from the main services on indri's minikube. This means the IdP is independent of the minikube cluster lifecycle.
Three deployments:
- **server** — HTTP/HTTPS interface, handles OIDC flows
- **worker** — Background tasks, blueprint application
- **redis** — Caching, sessions, task queue
## Database
Uses the shared CNPG `blumeops-pg` cluster on [[indri]], accessed cross-cluster via `pg.ops.eblu.me:5432`. Database `authentik` with managed role.
## Blueprints
Integrate Forgejo with Authentik OIDC (#228) ## Summary - Refactor Authentik blueprints: extract shared `admins` group into `common.yaml`, add `groups` scope mapping to all providers for group-based admin propagation - Add Forgejo OAuth2 provider and application blueprint (`forgejo.yaml`) - Add `forgejo-client-secret` to ExternalSecret and worker deployment env - Configure Forgejo `[oauth2_client]` with `ACCOUNT_LINKING=login` to safely link existing accounts - Update documentation (forgejo.md, authentik.md, federated-login.md) ## Deployment and Testing After merge, deployment requires these steps in order: 1. **Authentik (ArgoCD):** - `argocd app set authentik --revision feature/forgejo-authentik-oidc && argocd app sync authentik` - Verify: Forgejo app/provider visible in Authentik admin UI - Verify: Grafana SSO still works (blueprint refactor) 2. **Forgejo app.ini (Ansible):** - `mise run provision-indri -- --tags forgejo --check --diff` (dry run) - `mise run provision-indri -- --tags forgejo` (apply, restarts Forgejo) 3. **Create Forgejo auth source (CLI on indri):** ``` ssh indri 'sudo -u forgejo /opt/homebrew/bin/forgejo admin auth add-oauth \ --name authentik \ --provider openidConnect \ --key forgejo \ --secret "$(op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/Authentik (blumeops)/forgejo-client-secret")" \ --auto-discover-url https://authentik.ops.eblu.me/application/o/forgejo/.well-known/openid-configuration \ --scopes "openid email profile groups" \ --group-claim-name groups \ --admin-group admins' ``` 4. **Link eblume account:** Sign in with Authentik on Forgejo, confirm link with local password 5. **Verify:** `tea repo list`, Forgejo Actions, local password break-glass After merge: `argocd app set authentik --revision main && argocd app sync authentik` Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/228
2026-02-20 17:39:50 -08:00
Authentik configuration is managed via Blueprints (YAML) stored as a ConfigMap mounted into the worker at `/blueprints/custom/`. Current blueprints:
Integrate Forgejo with Authentik OIDC (#228) ## Summary - Refactor Authentik blueprints: extract shared `admins` group into `common.yaml`, add `groups` scope mapping to all providers for group-based admin propagation - Add Forgejo OAuth2 provider and application blueprint (`forgejo.yaml`) - Add `forgejo-client-secret` to ExternalSecret and worker deployment env - Configure Forgejo `[oauth2_client]` with `ACCOUNT_LINKING=login` to safely link existing accounts - Update documentation (forgejo.md, authentik.md, federated-login.md) ## Deployment and Testing After merge, deployment requires these steps in order: 1. **Authentik (ArgoCD):** - `argocd app set authentik --revision feature/forgejo-authentik-oidc && argocd app sync authentik` - Verify: Forgejo app/provider visible in Authentik admin UI - Verify: Grafana SSO still works (blueprint refactor) 2. **Forgejo app.ini (Ansible):** - `mise run provision-indri -- --tags forgejo --check --diff` (dry run) - `mise run provision-indri -- --tags forgejo` (apply, restarts Forgejo) 3. **Create Forgejo auth source (CLI on indri):** ``` ssh indri 'sudo -u forgejo /opt/homebrew/bin/forgejo admin auth add-oauth \ --name authentik \ --provider openidConnect \ --key forgejo \ --secret "$(op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/Authentik (blumeops)/forgejo-client-secret")" \ --auto-discover-url https://authentik.ops.eblu.me/application/o/forgejo/.well-known/openid-configuration \ --scopes "openid email profile groups" \ --group-claim-name groups \ --admin-group admins' ``` 4. **Link eblume account:** Sign in with Authentik on Forgejo, confirm link with local password 5. **Verify:** `tea repo list`, Forgejo Actions, local password break-glass After merge: `argocd app set authentik --revision main && argocd app sync authentik` Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/228
2026-02-20 17:39:50 -08:00
- **`common.yaml`** — shared identity resources (`admins` group)
- **`mfa.yaml`** — MFA enforcement on the default authentication flow (`not_configured_action: configure`)
Doc review: 5 stalest cards; scale back ai-docs rule; document heph CLI (#373) ## Doc review (5 stalest, all never-reviewed) Each card was verified against live state (ArgoCD app list/health, manifests, 1Password item fields, Mealie API probe) and stamped `last-reviewed: 2026-06-09`. | Card | Findings fixed | |------|----------------| | `reference/services/argocd.md` | Added Authentik SSO (public PKCE client, `--sso` login, admins→role:admin RBAC); documented dual-cluster management (minikube + ringtail k3s at `ringtail.tail8d86e.ts.net:6443`); corrected sync policy — the `apps` root is **manual**, not automated | | `reference/services/authentik.md` | Blueprint list grown from 5 to 10 files; OIDC client table now lists all 8 clients with types; secrets table updated to `postgresql-*` fields and per-client secrets | | `reference/services/grafana.md` | TeslaMate datasource moved to `pg.ops.eblu.me:5434` (ringtail); dashboard inventory refreshed (20 provisioned ConfigMaps); TeslaMate dashboards documented as init-container fetch from forge mirror at pinned tag; SSO role mapping wording corrected (Admin only for `admins` group) | | `reference/infrastructure/unifi.md` | UnPoller image is now locally built (`registry.ops.eblu.me/blumeops/unpoller`); verified namespace/port | | `how-to/mealie/plan-a-meal.md` | Procedure verified; **found the stored API token (`op://blumeops/mealie/credential`) returns 401** — operational fix in progress, doc content unchanged | ## AGENTS.md - **Scaled back the ai-docs rule** (per discussion): agents now start by finding and reading relevant docs; `mise run ai-docs` (~130K tokens now) and `ai-sources` become opt-in bulk loads. `agent-change-process.md` updated to match. The `ai-docs` mise task itself is kept for now — happy to retire it in a follow-up if desired. - **Documented the heph CLI** task workflow (list/show/context/log read paths; done/drop/skip/log/edit/task write paths) so future sessions can read and manipulate Blumeops tasks without rediscovery. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.eblu.me/eblume/blumeops/pulls/373
2026-06-09 16:05:01 -07:00
- One blueprint per OIDC client (provider, application, and policy binding): `grafana.yaml`, `forgejo.yaml`, `zot.yaml`, `argocd.yaml`, `jellyfin.yaml`, `mealie.yaml`, `paperless.yaml`, `heph.yaml`
Integrate Forgejo with Authentik OIDC (#228) ## Summary - Refactor Authentik blueprints: extract shared `admins` group into `common.yaml`, add `groups` scope mapping to all providers for group-based admin propagation - Add Forgejo OAuth2 provider and application blueprint (`forgejo.yaml`) - Add `forgejo-client-secret` to ExternalSecret and worker deployment env - Configure Forgejo `[oauth2_client]` with `ACCOUNT_LINKING=login` to safely link existing accounts - Update documentation (forgejo.md, authentik.md, federated-login.md) ## Deployment and Testing After merge, deployment requires these steps in order: 1. **Authentik (ArgoCD):** - `argocd app set authentik --revision feature/forgejo-authentik-oidc && argocd app sync authentik` - Verify: Forgejo app/provider visible in Authentik admin UI - Verify: Grafana SSO still works (blueprint refactor) 2. **Forgejo app.ini (Ansible):** - `mise run provision-indri -- --tags forgejo --check --diff` (dry run) - `mise run provision-indri -- --tags forgejo` (apply, restarts Forgejo) 3. **Create Forgejo auth source (CLI on indri):** ``` ssh indri 'sudo -u forgejo /opt/homebrew/bin/forgejo admin auth add-oauth \ --name authentik \ --provider openidConnect \ --key forgejo \ --secret "$(op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/Authentik (blumeops)/forgejo-client-secret")" \ --auto-discover-url https://authentik.ops.eblu.me/application/o/forgejo/.well-known/openid-configuration \ --scopes "openid email profile groups" \ --group-claim-name groups \ --admin-group admins' ``` 4. **Link eblume account:** Sign in with Authentik on Forgejo, confirm link with local password 5. **Verify:** `tea repo list`, Forgejo Actions, local password break-glass After merge: `argocd app set authentik --revision main && argocd app sync authentik` Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/228
2026-02-20 17:39:50 -08:00
Group membership is included in the `profile` scope claim (Authentik built-in). Services use `--group-claim-name groups` to read it.
Blueprint file: `argocd/manifests/authentik/configmap-blueprint.yaml`
## OIDC Clients
Doc review: 5 stalest cards; scale back ai-docs rule; document heph CLI (#373) ## Doc review (5 stalest, all never-reviewed) Each card was verified against live state (ArgoCD app list/health, manifests, 1Password item fields, Mealie API probe) and stamped `last-reviewed: 2026-06-09`. | Card | Findings fixed | |------|----------------| | `reference/services/argocd.md` | Added Authentik SSO (public PKCE client, `--sso` login, admins→role:admin RBAC); documented dual-cluster management (minikube + ringtail k3s at `ringtail.tail8d86e.ts.net:6443`); corrected sync policy — the `apps` root is **manual**, not automated | | `reference/services/authentik.md` | Blueprint list grown from 5 to 10 files; OIDC client table now lists all 8 clients with types; secrets table updated to `postgresql-*` fields and per-client secrets | | `reference/services/grafana.md` | TeslaMate datasource moved to `pg.ops.eblu.me:5434` (ringtail); dashboard inventory refreshed (20 provisioned ConfigMaps); TeslaMate dashboards documented as init-container fetch from forge mirror at pinned tag; SSO role mapping wording corrected (Admin only for `admins` group) | | `reference/infrastructure/unifi.md` | UnPoller image is now locally built (`registry.ops.eblu.me/blumeops/unpoller`); verified namespace/port | | `how-to/mealie/plan-a-meal.md` | Procedure verified; **found the stored API token (`op://blumeops/mealie/credential`) returns 401** — operational fix in progress, doc content unchanged | ## AGENTS.md - **Scaled back the ai-docs rule** (per discussion): agents now start by finding and reading relevant docs; `mise run ai-docs` (~130K tokens now) and `ai-sources` become opt-in bulk loads. `agent-change-process.md` updated to match. The `ai-docs` mise task itself is kept for now — happy to retire it in a follow-up if desired. - **Documented the heph CLI** task workflow (list/show/context/log read paths; done/drop/skip/log/edit/task write paths) so future sessions can read and manipulate Blumeops tasks without rediscovery. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.eblu.me/eblume/blumeops/pulls/373
2026-06-09 16:05:01 -07:00
| Client | Type |
|--------|------|
| [[grafana]] | Confidential |
| [[forgejo]] | Confidential |
| [[zot]] | Confidential |
| [[argocd]] | Public (PKCE, shared by web UI and CLI) |
| [[jellyfin]] | Confidential |
| [[mealie]] | Confidential |
| [[paperless]] | Confidential |
| heph | Public (PKCE, with `offline_access` for spoke sync refresh tokens) |
Doc review: 5 stalest cards; scale back ai-docs rule; document heph CLI (#373) ## Doc review (5 stalest, all never-reviewed) Each card was verified against live state (ArgoCD app list/health, manifests, 1Password item fields, Mealie API probe) and stamped `last-reviewed: 2026-06-09`. | Card | Findings fixed | |------|----------------| | `reference/services/argocd.md` | Added Authentik SSO (public PKCE client, `--sso` login, admins→role:admin RBAC); documented dual-cluster management (minikube + ringtail k3s at `ringtail.tail8d86e.ts.net:6443`); corrected sync policy — the `apps` root is **manual**, not automated | | `reference/services/authentik.md` | Blueprint list grown from 5 to 10 files; OIDC client table now lists all 8 clients with types; secrets table updated to `postgresql-*` fields and per-client secrets | | `reference/services/grafana.md` | TeslaMate datasource moved to `pg.ops.eblu.me:5434` (ringtail); dashboard inventory refreshed (20 provisioned ConfigMaps); TeslaMate dashboards documented as init-container fetch from forge mirror at pinned tag; SSO role mapping wording corrected (Admin only for `admins` group) | | `reference/infrastructure/unifi.md` | UnPoller image is now locally built (`registry.ops.eblu.me/blumeops/unpoller`); verified namespace/port | | `how-to/mealie/plan-a-meal.md` | Procedure verified; **found the stored API token (`op://blumeops/mealie/credential`) returns 401** — operational fix in progress, doc content unchanged | ## AGENTS.md - **Scaled back the ai-docs rule** (per discussion): agents now start by finding and reading relevant docs; `mise run ai-docs` (~130K tokens now) and `ai-sources` become opt-in bulk loads. `agent-change-process.md` updated to match. The `ai-docs` mise task itself is kept for now — happy to retire it in a follow-up if desired. - **Documented the heph CLI** task workflow (list/show/context/log read paths; done/drop/skip/log/edit/task write paths) so future sessions can read and manipulate Blumeops tasks without rediscovery. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.eblu.me/eblume/blumeops/pulls/373
2026-06-09 16:05:01 -07:00
Future clients: [[miniflux]]
## Secrets
Fix spider trap: disable SPA mode, remove index files, relax wiki-links (#290) ## Summary Fixes the Facebook crawler spider trap that's been generating infinite recursive URLs like `/how-to/tutorials/tutorials/how-to/explanation/...` for several days. **Root cause:** Quartz SPA mode + nginx `try_files` fallback to `index.html` meant any fabricated URL returned the root HTML shell with HTTP 200. Crawlers followed relative links from those fake URLs, creating infinite recursion. **Fix:** - Disable Quartz SPA mode (`enableSPA: false`) — all pages are now fully static HTML - Replace nginx SPA fallback with `=404` + Quartz's static `404.html` - Remove `robots.txt` exclusions (no longer needed) **Docs cleanup (Obsidian.nvim compat no longer needed):** - Delete hand-curated category index files (`tutorials.md`, `reference.md`, `how-to.md`, `explanation.md`) — Quartz auto-generates folder pages - Delete `postgresql-storage.md` (redirect stub) and `migrate-forgejo-from-brew.md` (stale history) - Drop `docs-check-index` and `docs-check-filenames` prek hooks - Rewrite `docs-check-links` to allow path-based wiki-links (`[[path/to/file]]`) and only error on true ambiguity - Add `ai-docs` doc tree listing to replace index files for AI context - Add natural cross-links from reference cards to fix orphan docs ## Deployment and Testing - [ ] Merge and let the build pipeline run - [ ] Verify docs.eblu.me serves pages correctly with full page loads - [ ] Verify non-existent URLs return 404 - [ ] Monitor crawler traffic — should drop to near zero for fabricated URLs Reviewed-on: https://forge.eblu.me/eblume/blumeops/pulls/290
2026-03-09 11:59:43 -07:00
Injected via [[external-secrets]] from the "Authentik (blumeops)" 1Password item (see [[create-authentik-secrets]] for setup).
| 1Password Field | Purpose |
|-----------------|---------|
| `secret-key` | Authentik secret key |
Doc review: 5 stalest cards; scale back ai-docs rule; document heph CLI (#373) ## Doc review (5 stalest, all never-reviewed) Each card was verified against live state (ArgoCD app list/health, manifests, 1Password item fields, Mealie API probe) and stamped `last-reviewed: 2026-06-09`. | Card | Findings fixed | |------|----------------| | `reference/services/argocd.md` | Added Authentik SSO (public PKCE client, `--sso` login, admins→role:admin RBAC); documented dual-cluster management (minikube + ringtail k3s at `ringtail.tail8d86e.ts.net:6443`); corrected sync policy — the `apps` root is **manual**, not automated | | `reference/services/authentik.md` | Blueprint list grown from 5 to 10 files; OIDC client table now lists all 8 clients with types; secrets table updated to `postgresql-*` fields and per-client secrets | | `reference/services/grafana.md` | TeslaMate datasource moved to `pg.ops.eblu.me:5434` (ringtail); dashboard inventory refreshed (20 provisioned ConfigMaps); TeslaMate dashboards documented as init-container fetch from forge mirror at pinned tag; SSO role mapping wording corrected (Admin only for `admins` group) | | `reference/infrastructure/unifi.md` | UnPoller image is now locally built (`registry.ops.eblu.me/blumeops/unpoller`); verified namespace/port | | `how-to/mealie/plan-a-meal.md` | Procedure verified; **found the stored API token (`op://blumeops/mealie/credential`) returns 401** — operational fix in progress, doc content unchanged | ## AGENTS.md - **Scaled back the ai-docs rule** (per discussion): agents now start by finding and reading relevant docs; `mise run ai-docs` (~130K tokens now) and `ai-sources` become opt-in bulk loads. `agent-change-process.md` updated to match. The `ai-docs` mise task itself is kept for now — happy to retire it in a follow-up if desired. - **Documented the heph CLI** task workflow (list/show/context/log read paths; done/drop/skip/log/edit/task write paths) so future sessions can read and manipulate Blumeops tasks without rediscovery. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.eblu.me/eblume/blumeops/pulls/373
2026-06-09 16:05:01 -07:00
| `postgresql-host` / `-port` / `-name` / `-user` / `-password` | PostgreSQL connection |
| `<client>-client-secret` | OIDC client secret, one per confidential client (grafana, forgejo, zot, jellyfin, mealie, paperless) |
The item also holds an `api-token` field (Authentik API access for admin scripting); it is not synced into the cluster.
## Container Image
Nix-built via `dockerTools.buildLayeredImage`. The entrypoint wrapper symlinks built-in blueprint directories from the Nix store into `/blueprints/` at runtime, allowing custom blueprints to coexist with defaults. `AUTHENTIK_BLUEPRINTS_DIR=/blueprints` overrides the hardcoded Nix store path.
## Related
- [[federated-login]] - How authentication works across BlumeOps
- [[grafana]] - First OIDC client
- [[deploy-authentik]] - Deployment how-to
Fix spider trap: disable SPA mode, remove index files, relax wiki-links (#290) ## Summary Fixes the Facebook crawler spider trap that's been generating infinite recursive URLs like `/how-to/tutorials/tutorials/how-to/explanation/...` for several days. **Root cause:** Quartz SPA mode + nginx `try_files` fallback to `index.html` meant any fabricated URL returned the root HTML shell with HTTP 200. Crawlers followed relative links from those fake URLs, creating infinite recursion. **Fix:** - Disable Quartz SPA mode (`enableSPA: false`) — all pages are now fully static HTML - Replace nginx SPA fallback with `=404` + Quartz's static `404.html` - Remove `robots.txt` exclusions (no longer needed) **Docs cleanup (Obsidian.nvim compat no longer needed):** - Delete hand-curated category index files (`tutorials.md`, `reference.md`, `how-to.md`, `explanation.md`) — Quartz auto-generates folder pages - Delete `postgresql-storage.md` (redirect stub) and `migrate-forgejo-from-brew.md` (stale history) - Drop `docs-check-index` and `docs-check-filenames` prek hooks - Rewrite `docs-check-links` to allow path-based wiki-links (`[[path/to/file]]`) and only error on true ambiguity - Add `ai-docs` doc tree listing to replace index files for AI context - Add natural cross-links from reference cards to fix orphan docs ## Deployment and Testing - [ ] Merge and let the build pipeline run - [ ] Verify docs.eblu.me serves pages correctly with full page loads - [ ] Verify non-existent URLs return 404 - [ ] Monitor crawler traffic — should drop to near zero for fabricated URLs Reviewed-on: https://forge.eblu.me/eblume/blumeops/pulls/290
2026-03-09 11:59:43 -07:00
- [[migrate-grafana-to-authentik]] - Grafana SSO migration from Dex
- [[build-authentik-from-source]] - Nix-based container build
- [[mirror-authentik-build-deps]] - Supply chain mirrors for the build
- [[external-secrets]] - Secrets injection from 1Password