# 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: 1. Go to Site Administration → Authentication Sources 2. Add new OAuth2 source 3. 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`) ## 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 encryption - `AUTHENTIK_REDIS__HOST`: Redis container hostname - `AUTHENTIK_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) 1. **Create Provider in Authentik** - Admin → Providers → Create → OAuth2/OpenID - Set name, redirect URIs, scopes 2. **Create Application** - Admin → Applications → Create - Link to provider - Set launch URL 3. **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. 1. **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) 2. **Create Application** - Admin → Applications → Create - Name: e.g., "Actual Budget" - Slug: `actual` - Provider: Select the proxy provider - Launch URL: `https://actual.vish.gg` 3. **Create Outpost** (if not exists) - Admin → Applications → Outposts - Create embedded outpost or deploy standalone - Add the application to the outpost 4. **Configure Nginx/Reverse Proxy** Add forward auth to your reverse proxy config: ```nginx 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: ```nginx # 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 | ### 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 | ### 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 | Mail | 192.168.0.154:8082 | Own auth | | ollama.vish.gg | Ollama | 192.168.0.200:11434 | API only | | 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 | 192.168.0.250:9751 | Own auth | ## 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: ```bash # 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 - [Cloudflare Tunnels](./cloudflare-tunnels.md) - [Port Forwarding Configuration](./port-forwarding-configuration.md) - [Security](./security.md) - [Grafana OAuth](../services/individual/grafana-oauth.md) - [Gitea OAuth](../services/individual/gitea.md#-oauth2-single-sign-on-authentik) - [Seafile OAuth](../services/individual/seafile-oauth.md) ## Change Log - **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