17 KiB
Authentik SSO Setup
Single Sign-On (SSO) for homelab services using Authentik.
Overview
Authentik provides centralized authentication for all homelab services via OAuth2/OpenID Connect.
- URL: https://sso.vish.gg
- Admin Interface: https://sso.vish.gg/if/admin/
- User Portal: https://sso.vish.gg/if/user/
- Host: Calypso NAS (Synology DS723+)
- Stack: Docker Compose via Portainer
Admin Credentials
- Username:
akadmin - Email:
admin@example.com - Password: REDACTED_PASSWORD in password manager
Architecture
┌──────────────────┐
│ Cloudflare │
│ (DNS + SSL) │
└────────┬─────────┘
│
┌────────▼─────────┐
│ sso.vish.gg │
│ (Authentik) │
│ Calypso NAS │
└────────┬─────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌──────────┐
│ Grafana │ │ Gitea │ │Portainer │
│gf.vish.gg│ │git.vish.gg│ │ internal │
│homelab-vm│ │ Calypso │ │ Calypso │
└─────────┘ └─────────┘ └──────────┘
OAuth2 Providers
Grafana
| Setting | Value |
|---|---|
| Client ID | lEGw1UJ9Mhk6QVrNA61rAsr59Kel9gAvdPQ1FAJA |
| Client Secret | ArP5XWdkwVyw9nvXZaqjE9sIjXdmIgpgI4ZR8oKvTUVLgmIGVvKU8T867diMGSQXgTcWQQPbdbEdXTU1v3y9RKMnAqu2k6V4xlmxwNYlCDuk5inxJSdoC0V8ICtZxk1X |
| Redirect URI | https://gf.vish.gg |
| Scopes | openid profile email |
Configuration File: hosts/vms/homelab-vm/monitoring.yaml
Gitea
| Setting | Value |
|---|---|
| Client ID | 7KamS51a0H7V8HyIsfMKNJ8COstZEFh4Z8Em6ZhO |
| Client Secret | 3IjyKCbHtgev6eMb1hYpQGHoGwPSRKda4ijRtbWfkhguNomxexxTiWtoWtyrXwGaF0ORj4D7D0kzB3Z1YN9DN5iz0HOKjAn5AdWJrSyxan02MjiwKmEriAbSGyh53uph |
| Redirect URI | https://git.vish.gg/user/oauth2/authentik/callback |
| Discovery URL | https://sso.vish.gg/application/o/gitea/.well-known/openid-configuration |
Configuration File: hosts/synology/calypso/gitea-server.yaml
Manual Setup Required: Add OAuth2 source in Gitea admin UI:
- Go to Site Administration → Authentication Sources
- Add new OAuth2 source
- Use Discovery URL for auto-configuration
Portainer
| Setting | Value |
|---|---|
| Client ID | fLLnVh8iUyJYdw5HKdt1Q7LHKJLLB8tLZwxmVhNs |
| Client Secret | xD9u47XbJd2g7vCeIyJC7MNvfEqytEnnHeVtJ7nU5Y1XGxYncXkejNAYkToUiRWcym3GpZIXgMpUnNNuUwud0Ff493ZwSHCiSKsk9n6RJLJ1iVvR20NdDnMe4YEGYXrt |
| Redirect URI | http://vishinator.synology.me:10000 |
| User Identifier | email |
Configuration: Via Portainer API (/api/settings)
Reactive Resume v5
| Setting | Value |
|---|---|
| Client ID | QU5qA7jLP9ghxy7iGMJoyZsCja2vY2Y2oGaLGjxA |
| Client Secret | wX1aFaby4aIABjLBBClYu4ukmIOjviL85GJBX8bAB3srQnt1BD31LcblRKyxzuv1yGwtsKLTFjwz12rUy6HknOqpIwk1QQ21jMjpWb1aa77iRG6lDkf4eNf8wWpE9Apo |
| Redirect URI | https://rx.vish.gg/api/auth/callback/custom |
| Discovery URL | https://sso.vish.gg/application/o/reactive-resume/.well-known/openid-configuration |
Configuration File: hosts/synology/calypso/reactive_resume_v5/docker-compose.yml (also live at /volume1/docker/rxv5/docker-compose.yml on Calypso)
Homarr
| Setting | Value |
|---|---|
| Client ID | 8oP0ha7gLjdz13MAPVsb7fe7TBkFBz7mt1eU8MEO |
| Client Secret | SpJXIGDk3SJfiS9GJwzH0fKrePsrumvCOmvFd2h0hEfxXMO77aCtpPEs6FShLTaUW5YxqgEDFkQi7q9NIOQDJTPQHlSy3nIeyDQmS2tVIV1BpSdGpnLQedouOkXACwe2 |
| Redirect URI | https://dash.vish.gg/api/auth/callback/oidc |
| Admin Group | Homarr Admins (Authentik group, pk=892da833-5283-4672-a906-7448ae3ba9b6) |
| Discovery URL | https://sso.vish.gg/application/o/homarr/.well-known/openid-configuration |
Configuration File: hosts/synology/atlantis/homarr.yaml
Note: SECRET_ENCRYPTION_KEY is required by Homarr — a 64-char hex key must be provided as an env var. The AUTH_OIDC_ADMIN_GROUP and AUTH_OIDC_OWNER_GROUP map to an Authentik group name.
Immich
| Setting | Value |
|---|---|
| Client ID | XSHhp1Hys1ZyRpbpGUv4iqu1y1kJXX7WIIFETqcL |
| Client Secret | mlbc4NbqiyRyUSqeUupaob7WsA3sURWExmoxYAcozClnmsdCPzGHlyO6zmErnS9YNyBsKOYoGUPvSTQPrE07UnYDLSMy286fycHoAJoc0cAN8BMc5cIif5kf88NSNCj2 |
| Redirect URIs | http://192.168.0.250:8212/auth/login, http://calypso.vish.local:8212/auth/login, app.immich:/ |
| Issuer URL | https://sso.vish.gg/application/o/immich/ |
| Button Text | Sign in with Authentik |
| Auto Register | true |
Configuration: Via immich-config.json mounted at /config/immich-config.json inside the container. Config file lives at /volume1/docker/immich/config/immich-config.json on Calypso and is tracked at /home/homelab/immich-config.json.
Note: Immich constructs the redirect URI dynamically from the hostname the browser used to access it — so every access hostname must be registered in Authentik. Currently registered: IP, calypso.vish.local, app.immich:/. mobileRedirectUri in the config file must be empty string — Immich's validator rejects custom URI schemes there.
Headplane
| Setting | Value |
|---|---|
| Provider PK | 16 |
| Client ID | 1xLx9TkufvLGKgq8UmQV2RfTB6raSpEjZExBOhJ4 |
| Client Secret | 4r4n96jBGc8MlonyHStiN09ow0txTwERLupt9hsoNswpicEnJZHgKwi38jYP5zlou5J525dVFUmXNSvnxwBJgKIIAfpC43zi8yUVtT0NYNdEBeYQOsh1YW5jK8nVPSdc |
| Redirect URI | https://headscale.vish.gg:8443/admin/oidc/callback |
| Issuer URL | https://sso.vish.gg/application/o/headplane/ |
| Scopes | openid profile email |
| Sub Mode | hashed_user_id |
Configuration File: hosts/synology/calypso/headplane-config.yaml (reference, secrets redacted). Live config at /volume1/docker/headscale/headplane/config.yaml on Calypso.
Note: Headplane is served at https://headscale.vish.gg:8443/admin — no separate domain. NPM proxy host 44 routes /admin to port 3002. First user to log in via OIDC is automatically assigned the Owner role.
NetBox
| Setting | Value |
|---|---|
| Provider PK | 23 |
| Client ID | BB7PiOu8xFOl58H2MUfl9IHISVLuJ4UwwMGvmJ9N |
| Client Secret | CRdRVCM13JN9bSiT2aU74cFXSI9GpVBLBShOFGBpVHOQ4brnDWOzk8I02cEww8Gcrr6GnsU0XdBxHTEpfvX2u9rhmey7XDT3XUVVh9ADaSldww83hp4hAzH5eNx1zKvB |
| Redirect URI | https://nb.vish.gg/oauth/complete/oidc/ |
| Discovery URL | https://sso.vish.gg/application/o/netbox/.well-known/openid-configuration |
| Scopes | openid profile email |
Configuration: NetBox configuration.py on homelab-vm (/home/homelab/docker/netbox/config/configuration.py). Uses python-social-auth with social_core.backends.open_id_connect.OpenIdConnectAuth backend. associate_by_email pipeline maps Authentik users to existing NetBox accounts by email.
Authentik Endpoints
| Endpoint | URL |
|---|---|
| Authorization | https://sso.vish.gg/application/o/authorize/ |
| Token | https://sso.vish.gg/application/o/token/ |
| User Info | https://sso.vish.gg/application/o/userinfo/ |
| JWKS | https://sso.vish.gg/application/o/{app-slug}/jwks/ |
| OpenID Config | https://sso.vish.gg/application/o/{app-slug}/.well-known/openid-configuration |
| End Session | https://sso.vish.gg/application/o/{app-slug}/end-session/ |
Docker Compose Configuration
Location: hosts/synology/calypso/authentik.yaml
Key environment variables:
AUTHENTIK_SECRET_KEY: Random secret for encryptionAUTHENTIK_REDIS__HOST: Redis container hostnameAUTHENTIK_POSTGRESQL__*: PostgreSQL connection settings
SSL/TLS Configuration
SSL is handled by Cloudflare Origin Certificate:
- Certificate ID:
lONWNn(Synology reverse proxy) - Covers:
*.vish.gg - Origin: Cloudflare Full (Strict) mode
DNS Configuration
| Domain | Type | Target | Proxy |
|---|---|---|---|
| sso.vish.gg | CNAME | calypso DDNS | Orange (proxied) |
Adding New Services
Method 1: OAuth2/OpenID (for apps that support it)
-
Create Provider in Authentik
- Admin → Providers → Create → OAuth2/OpenID
- Set name, redirect URIs, scopes
-
Create Application
- Admin → Applications → Create
- Link to provider
- Set launch URL
-
Configure Service
- Add OAuth2/OIDC settings to service config
- Use Authentik endpoints
- Test login flow
Method 2: Proxy Provider (for apps without OAuth support)
Use this for apps like Actual Budget, Paperless-NGX, etc.
-
Create Proxy Provider in Authentik
- Admin → Providers → Create → Proxy Provider
- Name: e.g., "actual-proxy"
- Authorization flow: default-provider-authorization-implicit-consent
- External host:
https://actual.vish.gg - Mode: Forward auth (single application)
-
Create Application
- Admin → Applications → Create
- Name: e.g., "Actual Budget"
- Slug:
actual - Provider: Select the proxy provider
- Launch URL:
https://actual.vish.gg
-
Create Outpost (if not exists)
- Admin → Applications → Outposts
- Create embedded outpost or deploy standalone
- Add the application to the outpost
-
Configure Nginx/Reverse Proxy
Add forward auth to your reverse proxy config:
location / { # Forward auth to Authentik auth_request /outpost.goauthentik.io/auth/nginx; error_page 401 = @goauthentik_proxy_signin; auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; auth_request_set $authentik_username $upstream_http_x_authentik_username; auth_request_set $authentik_groups $upstream_http_x_authentik_groups; auth_request_set $authentik_email $upstream_http_x_authentik_email; proxy_set_header X-authentik-username $authentik_username; proxy_set_header X-authentik-groups $authentik_groups; proxy_set_header X-authentik-email $authentik_email; # Your existing proxy_pass proxy_pass http://localhost:PORT; } location /outpost.goauthentik.io { proxy_pass https://sso.vish.gg/outpost.goauthentik.io; proxy_set_header Host $host; proxy_set_header X-Original-URL $scheme://$http_host$request_uri; } location @goauthentik_proxy_signin { internal; add_header Set-Cookie $auth_cookie; return 302 /outpost.goauthentik.io/start?rd=$request_uri; }
Bypassing Auth for Share Links
For services like Seafile that have share links:
# Allow share links without auth
location /f/ {
proxy_pass http://localhost:8611;
}
location /d/ {
proxy_pass http://localhost:8611;
}
# Everything else requires auth
location / {
auth_request /outpost.goauthentik.io/auth/nginx;
# ... rest of auth config
proxy_pass http://localhost:8611;
}
Services Protection Summary
OAuth2/OpenID Connect (Login Button)
Services with native OAuth support - users see a "Sign in with Authentik" button.
| Domain | Service | Backend | Port | Status |
|---|---|---|---|---|
| gf.vish.gg | Grafana | 192.168.0.210 | 3300 | ✅ Working |
| git.vish.gg | Gitea | 192.168.0.250 | 3052 | ✅ Working |
| sf.vish.gg | Seafile | 192.168.0.250 | 8611 | ✅ Working |
| vishinator.synology.me:10000 | Portainer | 192.168.0.250 | 9000 | ✅ Working |
| rx.vish.gg | Reactive Resume v5 | 192.168.0.250 | 4550 | ✅ Working |
| dash.vish.gg | Homarr | 192.168.0.200 | 7575 | ✅ Working |
| immich.vish.gg | Immich | 192.168.0.250 | 8212 | ✅ Working |
| headscale.vish.gg/admin | Headplane | 192.168.0.250 | 3002 | ✅ Working |
| nb.vish.gg | NetBox | 192.168.0.210 | 8443 | ✅ Working |
Proxy Provider (Forward Auth)
Services without OAuth support - Authentik intercepts all requests and requires login first.
| Domain | Service | Backend | Port | Status |
|---|---|---|---|---|
| paperless.vish.gg | Paperless-NGX | 192.168.0.250 | 8777 | ✅ Working |
| docs.vish.gg | Paperless-NGX | 192.168.0.250 | 8777 | ✅ Working |
| actual.vish.gg | Actual Budget | 192.168.0.250 | 8304 | ✅ Working |
| npm.vish.gg | NPM Admin | 192.168.0.250 | 81 | ✅ Working |
| kuma.vish.gg | Uptime Kuma | 192.168.0.66 | 3001 | ✅ Working — /status/* public, rest gated |
| ollama.vish.gg | Ollama | 192.168.0.200 | 11434 | ✅ Working |
| wizarr.vish.gg | Wizarr | 192.168.0.200 | 5690 | ❌ Removed — caused redirect loop; Wizarr uses own auth |
Services Without SSO
These services use their own authentication or are public.
| Domain | Service | Backend | Notes |
|---|---|---|---|
| sso.vish.gg | Authentik | 192.168.0.250:9000 | SSO itself |
| pw.vish.gg | Vaultwarden | 192.168.0.200:4080 | Own auth |
| ntfy.vish.gg | Ntfy | 192.168.0.210:8081 | Own auth |
| cal.vish.gg | Baikal | 192.168.0.200:12852 | CalDAV auth |
| dav.vish.gg | Seafile WebDAV | 192.168.0.250:8612 | WebDAV auth |
| mm.crista.love | Mattermost | 192.168.0.154:8065 | Own auth |
| mastodon.vish.gg | Mastodon | 192.168.0.154:3000 | Own auth |
| mx.vish.gg | 192.168.0.154:8082 | Own auth | |
| ollama.vish.gg | Ollama | 192.168.0.200:11434 | See Forward Auth table above |
| retro.vish.gg | Retro Site | 192.168.0.250:8025 | Static site |
| rackula.vish.gg | Rackula | 192.168.0.250:3891 | Own auth |
| ost.vish.gg | OpenSpeedTest | 192.168.0.250:8004 | Public |
Other Domains
| Domain | Service | Backend | Notes |
|---|---|---|---|
| hoarder.thevish.io | Hoarder | 192.168.0.210:3000 | Own auth |
| matrix.thevish.io | Matrix | 192.168.0.154:8081 | Own auth |
| joplin.thevish.io | Joplin Server | 192.168.0.200:22300 | Own auth |
| meet.thevish.io | Jitsi | 192.168.0.200:5443 | Public |
| binterest.thevish.io | Binternet | 192.168.0.210:21544 | Own auth |
| crista.love | Personal Site | 192.168.0.100:28888 | Static |
| rxv4access.vish.gg | Reactive Resume v4 | 192.168.0.250:9751 | STALE - 525 SSL error, dead instance |
Troubleshooting
OAuth Login Fails with "Unauthorized"
- Verify user has email set in Authentik
- Check redirect URI matches exactly
- Verify client secret is correct
Certificate Errors
- Ensure Cloudflare proxy is enabled (orange cloud)
- Verify origin certificate is valid
- Check Synology reverse proxy SSL settings
User Auto-Creation Not Working
- Enable "Auto Create Users" in service OAuth settings
- Verify email scope is requested
- Check user identifier matches (email/username)
Recovery Access
If locked out of Authentik admin, you can create a recovery token:
# Via Portainer exec or SSH to Calypso
docker exec -it Authentik-SERVER ak create_recovery_key 10 akadmin
This generates a one-time recovery URL valid for 10 minutes.
Related Documentation
Change Log
- 2026-03-17: Added NetBox OIDC provider (pk=23) — nb.vish.gg, associate_by_email pipeline
- 2026-03-17: Removed Wizarr forward auth from NPM (wizarr has own auth, forward auth caused redirect loop)
- 2026-03-11: Added Headplane OIDC provider (pk=16) — Headscale web UI at headscale.vish.gg/admin, port 3002
- 2026-03-08: Added Forward Auth for Uptime Kuma (kuma.vish.gg), Ollama (ollama.vish.gg), Wizarr (wizarr.vish.gg)
- 2026-03-08: Kuma /status/* and Wizarr /i/* paths are public; all other paths gated
- 2026-03-08: Removed Forward Auth from dash.vish.gg NPM proxy (Homarr handles auth natively via OIDC)
- 2026-03-08: Disabled Uptime Kuma built-in auth (disableAuth=true in SQLite); Authentik is sole gate
- 2026-03-08: Calibre-Web started on port 8183 (8083 was occupied by Watchtower)
- 2026-03-08: Added OIDC for Reactive Resume v5 (rx.vish.gg), Homarr (dash.vish.gg), Immich (immich.vish.gg) — all working
- 2026-03-08: Fixed Homarr startup crash — SECRET_ENCRYPTION_KEY is mandatory (64-char hex)
- 2026-03-08: Immich OAuth configured via immich-config.json mount (not Admin UI); mobileRedirectUri must be empty
- 2026-03-08: Immich stack.env added to repo so stack is self-contained (no Portainer env injection needed)
- 2026-03-08: Flagged rxv4access.vish.gg as stale (dead RR v4 instance, 525 SSL error)
- 2026-01-31: Verified all OAuth2 and Forward Auth services working
- 2026-01-31: Fixed Grafana OAuth "InternalError" - added scope mappings to provider
- 2026-01-31: Removed Forward Auth from NPM for gf.vish.gg (conflicts with native OAuth)
- 2026-01-31: Added scope mappings to Gitea, Portainer, Seafile OAuth2 providers
- 2026-01-31: Updated comprehensive service protection summary