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

287 lines
12 KiB
Markdown

# 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.Enabled``true`, `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`:
```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.com` → `http://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:8080` → `openproject: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:80` → `http://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:3001` → `http://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.com` → `http://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:
```bash
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) |