kitestacks-homelab/docs/authentik-sso-setup.md
Kenpat7177 ea8b426f23 feat: configure Authentik SSO for all kitestacks.com services
- Enable OIDC in Kavita appsettings.json (Authority, ClientId, Enabled)
- Add OIDC env vars to BookStack compose + APP_URL + kitestacks network
- Add OIDC env vars to OpenProject compose + kitestacks network declaration
- Add kitestacks network + error reporting setting to Authentik compose
- Create .env secret placeholders for BookStack and OpenProject
- Add comprehensive SSO setup guide: docs/authentik-sso-setup.md
- Version bump: v1.3.883 → v1.3.884

Services getting native OIDC: Grafana, OpenWebUI, Forgejo, BookStack, OpenProject, Kavita
Services getting proxy auth:  Shaarli, Uptime Kuma, LiteLLM
Excluded: Portainer, Prometheus, Node Exporter, OpenRouter

Manual steps pending: Authentik admin UI app creation, Forgejo OAuth source, Cloudflare tunnel updates.
See docs/authentik-sso-setup.md for the full checklist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 14:42:11 -05:00

12 KiB

KiteStacks Authentik SSO Setup

Established: 2026-06-08
Author: kenpat
Status: In Progress — config files deployed, manual Authentik UI steps pending


Architecture

All services sit behind Cloudflare Tunnels on the kitestacks Docker network.
cloudflared routes external traffic directly to each service container by hostname.
Authentik (authentik:9000) is the single identity provider.

Internet → Cloudflare → cloudflared → [service container]
                                          ↕
                                 Authentik auth check

Two integration patterns are used:

Pattern How it works Services
Native OIDC/OAuth2 App calls Authentik directly for login Grafana, OpenWebUI, Forgejo, BookStack, OpenProject, Kavita
Authentik Proxy Provider Cloudflare tunnel → Authentik (embedded outpost) → service Shaarli, Uptime Kuma, LiteLLM

SSO Status

Service Subdomain Port Method Status
Authentik auth.kitestacks.com 9000 (is the IdP) Running
Grafana grafana.kitestacks.com 3000 OAuth2 ⚠️ env set, Authentik app needed
Kite AI (OpenWebUI) ai.kitestacks.com 8080 OIDC ⚠️ env set, Authentik app needed
Forgejo gitforge.kitestacks.com 3000 OAuth2 ⚠️ Forgejo admin UI config needed
BookStack books.kitestacks.com* 80 OIDC ⚠️ env set, Authentik app needed, CF tunnel needed
OpenProject tasks.kitestacks.com 80 OIDC ⚠️ env set, Authentik app needed
Kavita kavita.kitestacks.com 5000 OIDC ⚠️ appsettings.json updated, Authentik app needed
Shaarli links.kitestacks.com 80 Proxy ⚠️ Authentik Proxy Provider needed + CF tunnel update
Uptime Kuma status.kitestacks.com 3001 Proxy ⚠️ Authentik Proxy Provider needed + CF tunnel update
LiteLLM llm.kitestacks.com 4000 Proxy ⚠️ Authentik Proxy Provider needed + CF tunnel update
Portainer portainer.kitestacks.com 9000 🚫 SSO excluded
Prometheus prometheus.kitestacks.com 9090 🚫 SSO excluded
Node Exporter node-exporter.kitestacks.com 9100 🚫 SSO excluded
OpenRouter openrouter.ai 🚫 external, excluded

*BookStack subdomain placeholder — update APP_URL in apps/bookstack/docker-compose.yml.


Files Changed (2026-06-08)

File What changed
apps/authentik/docker-compose.yml Added kitestacks network declaration, AUTHENTIK_ERROR_REPORTING__ENABLED: false
apps/kavita/config/appsettings.json OpenIdConnectSettings.Enabledtrue, Authority set
apps/bookstack/docker-compose.yml OIDC env vars added, kitestacks network added, APP_URL updated
apps/bookstack/.env Created with BOOKSTACK_OIDC_SECRET placeholder
apps/openproject/docker-compose.yml OIDC env vars added, kitestacks network declared
apps/openproject/.env Created with OPENPROJECT_OIDC_SECRET placeholder

Step 1 — Authentik Admin UI: Create Providers and Applications

Go to https://auth.kitestacks.com → Admin Interface.

For each native OIDC service, create one OAuth2/OpenID Provider:

General settings (all providers):

  • Signing Key: select the default RS256 key
  • Token validity: 10 minutes (access), 30 days (refresh)

1. Grafana

  • Providers → Create → OAuth2/OpenID Provider
    • Name: Grafana
    • Client type: Confidential
    • Client ID: grafana
    • Redirect URIs: https://grafana.kitestacks.com/login/generic_oauth
    • Scopes: openid, email, profile
  • Applications → Create
    • Name: Grafana, Slug: grafana
    • Provider: Grafana (above)
  • Copy the Client Secret → put it in /home/kenpat/docker/grafana/.env:
    GRAFANA_OAUTH_CLIENT_SECRET=<paste_secret>
    
  • Restart: cd ~/docker/grafana && docker compose up -d

2. Kite AI (Open WebUI)

  • Providers → Create → OAuth2/OpenID Provider
    • Name: Open WebUI, Client ID: open-webui
    • Redirect URIs: https://ai.kitestacks.com/oauth/oidc/callback
    • Scopes: openid, email, profile
  • Applications → Create: Name: Kite AI, Slug: open-webui
  • Copy secret → /home/kenpat/docker/kite-ai/.env:
    OPENWEBUI_OAUTH_CLIENT_SECRET=<paste_secret>
    
  • Restart: cd ~/docker/kite-ai && docker compose up -d

3. Kavita

  • Providers → Create → OAuth2/OpenID Provider
    • Name: Kavita, Client ID: kavita
    • Redirect URIs: https://kavita.kitestacks.com/api/Account/OIDCCallback
    • Scopes: openid, email, profile
  • Applications → Create: Name: Kavita, Slug: kavita
  • Copy secret → /home/kenpat/docker/kavita/config/appsettings.json:
    "Secret": "<paste_secret>"
    
  • Restart: cd ~/docker/kavita && docker compose restart (if a compose exists) or docker restart kavita

4. BookStack

  • Providers → Create → OAuth2/OpenID Provider
    • Name: BookStack, Client ID: bookstack
    • Redirect URIs: https://books.kitestacks.com/oidc/callback (adjust to your actual BookStack subdomain)
    • Scopes: openid, email, profile
  • Applications → Create: Name: BookStack, Slug: bookstack
  • Copy secret → /home/kenpat/docker/bookstack/.env:
    BOOKSTACK_OIDC_SECRET=<paste_secret>
    
  • Set the real subdomain in /home/kenpat/docker/bookstack/docker-compose.yml:
    • Update APP_URL=https://<your-actual-bookstack-subdomain>.kitestacks.com
  • Restart: cd ~/docker/bookstack && docker compose up -d
  • In Cloudflare dashboard: add tunnel route <bookstack-subdomain>.kitestacks.comhttp://bookstack:80

5. OpenProject

  • Providers → Create → OAuth2/OpenID Provider
    • Name: OpenProject, Client ID: openproject
    • Redirect URIs: https://tasks.kitestacks.com/auth/oidc/callback
    • Scopes: openid, email, profile
  • Applications → Create: Name: OpenProject, Slug: openproject
  • Copy secret → /home/kenpat/docker/openproject/.env:
    OPENPROJECT_OIDC_SECRET=<paste_secret>
    
  • Restart: cd ~/docker/openproject && docker compose up -d
    • Note: Container is currently running openproject/community:13 but compose specifies openproject/openproject:15. Recreation will upgrade it. Verify data migration after restart. The Cloudflare tunnel for tasks.kitestacks.com may need updating from openproject:8080openproject:80 after the upgrade.

For proxy services, create Proxy Providers:

These services have no native OIDC. Authentik will act as the reverse proxy.

After creating each Proxy Provider + Application, add all three to the Embedded Outpost: Outposts → authentik Embedded Outpost → Edit → move all three proxy applications to "Selected Applications".

6. Shaarli

  • Providers → Create → Proxy Provider
    • Name: Shaarli
    • Mode: Reverse Proxy
    • External host: https://links.kitestacks.com
    • Internal host: http://shaarli:80
    • Internal host SSL validation: off
  • Applications → Create: Name: Shaarli, Slug: shaarli
  • Cloudflare Tunnel: Change links.kitestacks.com route from http://shaarli:80http://authentik:9000

7. Uptime Kuma

  • Providers → Create → Proxy Provider
    • Name: Uptime Kuma
    • Mode: Reverse Proxy
    • External host: https://status.kitestacks.com
    • Internal host: http://uptime-kuma:3001
  • Applications → Create: Name: Uptime Kuma, Slug: uptime-kuma
  • Cloudflare Tunnel: Change status.kitestacks.com route from http://uptime-kuma:3001http://authentik:9000

8. LiteLLM (when ready to expose publicly)

  • Providers → Create → Proxy Provider
    • Name: LiteLLM
    • Mode: Reverse Proxy
    • External host: https://llm.kitestacks.com
    • Internal host: http://kite-litellm:4000
  • Applications → Create: Name: LiteLLM, Slug: litellm
  • Cloudflare Tunnel: Add route llm.kitestacks.comhttp://authentik:9000

Step 2 — Forgejo: Add Authentik OAuth2 Source

Forgejo stores OAuth sources in its database (not in app.ini), so this requires the Forgejo admin UI.

  1. Go to https://gitforge.kitestacks.com → Site Administration → Authentication Sources
  2. Click Add Authentication Source
  3. Settings:
    • Authentication Type: OAuth2
    • Authentication Name: authentik
    • OAuth2 Provider: OpenID Connect
    • Client ID: forgejo
    • Client Secret: (create an Authentik app first — see below)
    • OpenID Connect Auto Discovery URL: https://auth.kitestacks.com/application/o/forgejo/.well-known/openid-configuration
    • Additional scopes: email profile
  4. Save

Create the Authentik app for Forgejo first:

  • Provider: OAuth2/OpenID, Client ID: forgejo
  • Redirect URI: https://gitforge.kitestacks.com/user/oauth2/authentik/callback
  • Application slug: forgejo

Step 3 — Cloudflare Tunnel Updates

In the Cloudflare Zero Trust Dashboard → Networks → Tunnels → your tunnel → Configure → Public Hostnames:

Hostname Change From Change To
links.kitestacks.com http://shaarli:80 http://authentik:9000
status.kitestacks.com http://uptime-kuma:3001 http://authentik:9000
llm.kitestacks.com (new) http://authentik:9000
tasks.kitestacks.com http://openproject:8080 http://openproject:80 (after OpenProject upgrade)
<bookstack-subdomain>.kitestacks.com (new) http://bookstack:80

Step 4 — Restart Containers After Config Changes

After filling in all secrets in the .env files:

cd ~/docker/grafana        && docker compose up -d
cd ~/docker/kite-ai        && docker compose up -d
cd ~/docker/bookstack      && docker compose up -d
cd ~/docker/openproject    && docker compose up -d
cd ~/docker/authentik      && docker compose up -d
docker restart kavita

Troubleshooting

OIDC redirect loop / 400 error

  • Check that the Redirect URI in the Authentik provider exactly matches what the app sends.
  • Grafana: https://grafana.kitestacks.com/login/generic_oauth (no trailing slash)

Kavita "OIDC is not configured" message

  • The appsettings.json change requires a container restart: docker restart kavita
  • Verify Enabled: true and Secret is not empty.

BookStack redirects to http://192.168.1.205:6875

  • APP_URL must be updated to the real HTTPS domain and the container recreated.

OpenProject: OIDC provider not visible in login

  • Env var format is version-specific. If env vars don't work in v15, configure via: Administration → Authentication → OpenID Connect Providers → Add

Proxy services (Shaarli/Uptime Kuma) show Authentik login but then 502

  • Verify the Embedded Outpost has the proxy providers assigned.
  • Verify internal host is reachable: docker exec authentik curl -v http://shaarli:80

Service-to-Container Name Reference

Subdomain Container Name Internal Port
auth.kitestacks.com authentik 9000
grafana.kitestacks.com grafana 3000
ai.kitestacks.com kite-openwebui 8080
gitforge.kitestacks.com forgejo 3000
tasks.kitestacks.com openproject 80 (after upgrade)
kavita.kitestacks.com kavita 5000
links.kitestacks.com shaarli 80
status.kitestacks.com uptime-kuma 3001
llm.kitestacks.com kite-litellm 4000
www.kitestacks.com homepage 3000
portainer.kitestacks.com portainer 9000 (excluded)
prometheus.kitestacks.com prometheus 9090 (excluded)
node-exporter.kitestacks.com node-exporter 9100 (excluded)