Authentik: A Self-Hosted Identity Provider for Everything
Every self-hosted stack eventually grows to the point where managing separate logins for Grafana, Gitea, Nextcloud, Proxmox, Portainer, Jellyfin, and a dozen other services becomes painful. Password reuse, no MFA enforcement, and no central audit log of who logged in to what. The obvious fix is Single Sign-On — one login, one MFA prompt, everything else flows through.
The enterprise answer is Okta or Azure AD. The self-hosted answer is Authentik: a full-featured identity provider that speaks OIDC, OAuth2, SAML, LDAP, SCIM, and RADIUS. It’s mature (used in production at thousands of organizations), actively developed, and runs comfortably on the same homelab hardware as the rest of your stack.
This guide walks through deploying Authentik, connecting your first few applications, setting up an LDAP outpost for legacy services, and hardening the installation for production use.
What Authentik Provides
- SSO via OIDC/OAuth2: Any modern app with OAuth2 support (Grafana, Gitea, Nextcloud, ArgoCD, Portainer, VS Code Server, etc.) can authenticate through Authentik
- SAML 2.0: For enterprise apps and anything that speaks SAML rather than OIDC
- LDAP Outpost: Expose a virtual LDAP directory so legacy apps that only understand LDAP can authenticate against Authentik’s user store
- RADIUS Outpost: For network devices like VPNs and switches that authenticate via RADIUS
- Proxy Outpost: Put Authentik in front of apps that have no auth at all — Authentik handles the login and passes verified headers
- MFA enforcement: TOTP, WebAuthn (hardware keys, passkeys, biometrics), SMS
- User enrollment flows: Invite-based registration, email verification, self-service password reset
- Audit log: Every authentication event, policy evaluation, and admin action is logged
- Social login: Forward authentication to Google, GitHub, Discord, and others while still managing users centrally
Architecture Overview
Authentik runs as two containers: a server (handles web UI, admin, and authentication flows) and a worker (handles background tasks, policy evaluation, and outpost communication). Both share a PostgreSQL database and Redis.
Browser / Client App
│
▼
Reverse Proxy (Traefik / nginx)
│
▼
Authentik Server (:9000 / :9443)
│
┌────┴────────────────────┐
│ │
PostgreSQL Redis
(user store, (session cache,
flow state, rate limiting,
audit log) task queue)
│
Authentik Worker
(background jobs,
LDAP/Proxy outpost)
Deploying with Docker Compose
|
|
Generate the required secrets before starting:
|
|
|
|
|
|
Access the admin UI at http://localhost:9000/if/admin/ and the user-facing flows at http://localhost:9000/.
Traefik Integration
Most homelab setups route through Traefik. Configure Authentik behind Traefik with HTTPS:
|
|
Core Concepts
Before wiring up apps, understand Authentik’s building blocks:
Providers: Define how an application authenticates — OIDC/OAuth2, SAML, LDAP, Proxy, RADIUS. Each provider implements a protocol.
Applications: The entry in Authentik’s catalog that ties a provider to a name, icon, and access policy. Users see Applications in their dashboard.
Outposts: Deployed services that handle specific protocols — the Proxy outpost intercepts requests before they hit your app, the LDAP outpost presents a virtual LDAP server.
Flows: Directed graphs of stages that define the authentication process. The default login flow goes: Identification → Password → MFA (if enrolled). You can customize these extensively.
Policies: Rules that gate access to applications. Bind a policy to an application to restrict access to specific groups, IP ranges, or evaluation results.
Blueprints: YAML-defined infrastructure-as-code for Authentik’s configuration — providers, applications, flows, and policies expressed as code rather than clicks.
Connecting Applications via OIDC
Grafana
In the Authentik Admin UI:
-
Create a Provider: Admin → Providers → Create → OAuth2/OIDC Provider
- Name:
Grafana - Client type: Confidential
- Redirect URIs:
https://grafana.yourdomain.com/login/generic_oauth - Copy the Client ID and Client Secret
- Name:
-
Create an Application: Admin → Applications → Create
- Name:
Grafana - Slug:
grafana - Provider:
Grafana(the one just created)
- Name:
Then configure Grafana to use it:
|
|
Or via environment variables in Docker Compose:
|
|
Gitea / Forgejo
In Authentik:
- Create an OIDC Provider with redirect URI:
https://gitea.yourdomain.com/user/oauth2/authentik/callback - Create an Application linked to that provider
In Gitea’s admin panel, Site Administration → Authentication Sources → Add Authentication Source:
- Type: OAuth2
- Name: authentik
- OAuth2 Provider: OpenID Connect
- Client ID/Secret: from Authentik
- OpenID Connect Auto Discovery URL:
https://auth.yourdomain.com/application/o/gitea/.well-known/openid-configuration
Portainer
Redirect URI: https://portainer.yourdomain.com
In Portainer: Settings → Authentication → OAuth → Custom
- Client ID/Secret: from Authentik
- Authorization URL:
https://auth.yourdomain.com/application/o/authorize/ - Access Token URL:
https://auth.yourdomain.com/application/o/token/ - Resource URL:
https://auth.yourdomain.com/application/o/userinfo/ - Redirect URL:
https://portainer.yourdomain.com - User Identifier:
preferred_username - Scopes:
openid email profile
ArgoCD
|
|
|
|
The Proxy Outpost: SSO for Apps Without Native Auth
Many self-hosted apps have no authentication at all — or have auth you can’t integrate with OIDC. The Authentik proxy outpost sits in front of these apps and handles authentication before the request reaches the app.
Setting Up the Proxy Outpost
-
In Authentik Admin: Providers → Create → Proxy Provider
- Name:
Heimdall Proxy(or whatever app) - Mode: Forward auth (single application)
- External host:
https://heimdall.yourdomain.com
- Name:
-
Create an Application for it
-
Admin → Outposts → Create
- Type: Proxy
- Integrate with the providers you just created
-
Authentik automatically deploys a container via the Docker socket. Or deploy it manually:
|
|
- Add the Traefik middleware to any app that should be protected:
|
|
Now visiting heimdall.yourdomain.com redirects to Authentik’s login page. After authentication, the proxy forwards the request with headers like X-authentik-username and X-authentik-email so the app knows who’s logged in.
LDAP Outpost: Legacy App Support
Some apps — particularly self-hosted ones from the late 2000s or early 2010s — only understand LDAP for authentication. Gitea (optional), Nextcloud (optional), and many network devices fall into this category. Authentik’s LDAP outpost presents a virtual LDAP directory backed by Authentik’s user store.
Deploy the LDAP Outpost
-
Admin → Outposts → Create
- Type: LDAP
- Bind as:
cn=ldapservice,ou=serviceaccounts,dc=ldap,dc=goauthentik,dc=io
-
Deploy the outpost container:
|
|
Configure a Service to Use LDAP
Example — Nextcloud LDAP configuration:
LDAP server: authentik-ldap (or the container IP/hostname)
Port: 3389
DN: ou=users,dc=ldap,dc=goauthentik,dc=io
Bind DN: cn=ldapservice,ou=serviceaccounts,dc=ldap,dc=goauthentik,dc=io
Bind password: <your service account password in Authentik>
User search base: ou=users,dc=ldap,dc=goauthentik,dc=io
User filter: (objectClass=user)
The virtual LDAP tree Authentik exposes:
dc=ldap,dc=goauthentik,dc=io
├── ou=users
│ ├── cn=alice # Regular users
│ ├── cn=bob
│ └── cn=carol
├── ou=groups
│ ├── cn=nextcloud-users
│ └── cn=nextcloud-admins
└── ou=serviceaccounts
└── cn=ldapservice # Bind account for services
Policies and Access Control
Policies control who can access which applications. They’re evaluated at login time and can check group membership, IP address, user attributes, and more.
Group-Based Access Policy
-
Admin → Groups → Create groups:
nextcloud-users,grafana-admins,homelab-users -
Add users to groups via Admin → Users → select user → Groups tab
-
Bind a policy to an Application:
- Admin → Applications → select app → Policy Bindings
- Create Binding → Group →
nextcloud-users - Users not in this group see “Permission denied” instead of a login form
Expression Policies (Python)
For more complex rules, write a Python expression policy:
|
|
|
|
Enrollment Flows and Invitation Links
Authentik’s flows are fully customizable. The default enrollment flow does email verification, but you can build invite-only enrollment with single-use tokens:
-
Admin → Flows → Create
- Designation: Enrollment
- Name:
Invite-Only Enrollment
-
Add stages:
- Invitation Stage: validate a token from the invite link
- User Write Stage: create the user account
- Email Verification Stage: send and verify email
- Prompt Stage: collect name, password
- User Login Stage: log them in after enrollment
-
Admin → Invitations → Create Invitation → share the link
The invite link: https://auth.yourdomain.com/if/flow/invite-only-enrollment/?itoken=abc123
MFA Configuration
TOTP (Google Authenticator, Authy)
-
Admin → Stages → Create → Authenticator TOTP Stage
- Digits: 6
- Configure stage name:
totp-setup
-
Add to your authentication flow after the password stage
- Add TOTP Validation Stage to the login flow (after password)
- With a TOTP Setup Stage as the fallback (if not enrolled, prompt to enroll)
WebAuthn (Passkeys, YubiKey)
-
Admin → Stages → Create → Authenticator WebAuthn Stage
- User verification: Required (enforces biometric/PIN)
- Resident key requirement: Preferred (enables passkey mode)
-
Users enroll their device at
https://auth.yourdomain.com/user/→ MFA Devices
Enforcing MFA for Specific Applications
Bind an MFA policy to sensitive applications:
|
|
Blueprints: Configuration as Code
Managing Authentik via the UI is fine for initial setup. For production, use blueprints to version-control your configuration:
|
|
Apply blueprints:
|
|
Store all your blueprints in a Git repository and apply them in CI to keep Authentik configuration in sync with your infrastructure code.
Social Login: Delegate to GitHub or Google
Let users log in with their GitHub or Google account, while still managing them centrally in Authentik:
-
Create a GitHub OAuth App at github.com/settings/developers
- Callback URL:
https://auth.yourdomain.com/source/oauth/callback/github/
- Callback URL:
-
Add the Source in Authentik: Admin → Federation & Social login → GitHub
- Client ID/Secret: from GitHub
- Consumer Key Name:
github - Enrollment flow: your invite-only enrollment flow (so GitHub users go through the same verification)
Now the login page shows a “Sign in with GitHub” button. The GitHub identity is linked to an Authentik account, and all your group-based access policies still apply.
Monitoring and Audit
Application Log
Every authentication event is logged. View them at Admin → Events → Logs:
- Filter by user, application, or event type
- Export to CSV for compliance reporting
- Set up event notifications for suspicious activity
Prometheus Metrics
Authentik exposes metrics at /-/metrics:
|
|
Key metrics:
|
|
Alerting on Suspicious Activity
|
|
Production Hardening
Secret Key Rotation
If you need to rotate the secret key (e.g., after suspected compromise):
|
|
Rate Limiting
Authentik includes built-in rate limiting, but add nginx/Traefik rate limits in front for additional protection:
|
|
Backup Strategy
|
|
Restrict Admin UI Access
The admin interface at /if/admin/ should not be publicly accessible. Restrict it to your home/VPN network:
|
|
Quick Integration Reference
| Application | Protocol | Notes |
|---|---|---|
| Grafana | OIDC | Full role mapping via role_attribute_path |
| Gitea / Forgejo | OIDC | OAuth2 source in admin panel |
| Nextcloud | OIDC or LDAP | Social Login app for OIDC |
| ArgoCD | OIDC | Group-based RBAC |
| Portainer | OIDC | OAuth settings in UI |
| Proxmox | OIDC | Realm configuration |
| Jellyfin | OIDC | SSO Plugin required |
| Vaultwarden | OIDC + SSO Plugin | Needs Vaultwarden config |
| VS Code Server | Proxy Outpost | No native auth needed |
| Heimdall | Proxy Outpost | Dashboard has no auth |
| Netdata | Proxy Outpost | Protect metrics |
| Paperless-ngx | OIDC | Native OIDC support |
| Synology DSM | OIDC | OIDC SSO app in DSM |
| pfSense / OPNsense | RADIUS Outpost | Network auth |
Conclusion
Authentik transforms a sprawling collection of individually-authenticated services into a unified platform with one login, one MFA policy, one audit log, and one place to revoke access. When a team member leaves or a device is compromised, you disable one account in Authentik rather than hunting down passwords across a dozen applications.
The proxy outpost is a particularly powerful feature — apps that have no authentication at all suddenly get SSO without any code changes. The LDAP outpost bridges the gap to legacy applications that can’t speak OIDC. And the blueprint system ensures your identity infrastructure is version-controlled and reproducible.
Start with Docker Compose, wire up two or three apps via OIDC, and feel the difference of a unified login experience. The rest of the integrations follow naturally.
Comments