As your homelab grows from a handful of containers to a dozen services — Gitea, Grafana, Vaultwarden, Pi-hole admin, Portainer, Proxmox — managing separate credentials for each becomes a liability. Every service has its own login, its own password policy (or lack thereof), and its own notion of multi-factor authentication.
Authentik solves this. It is an open-source Identity Provider (IdP) that provides SSO, MFA, and centralized access policies. Deploy it behind Traefik, and every service in your homelab can authenticate through a single portal with TOTP or WebAuthn.
This guide covers deploying Authentik with Docker Compose, configuring the Traefik forward-auth middleware, creating applications and providers, setting up access policies, and onboarding your homelab services one by one.
Authentik vs the Alternatives
| Feature | Authentik | Authelia | Keycloak |
|---|---|---|---|
| Deployment complexity | Moderate | Low | High |
| Built-in OIDC/OAuth2 | Yes | Yes (OIDC only) | Yes |
| LDAP outpost | Yes | No | Yes (external) |
| WebAuthn (passkeys) | Yes | Yes | Yes |
| Admin UI | Rich web UI | Minimal | Complex |
| User self-service portal | Yes | Limited | Yes |
| Traefik forward-auth | Native | Native | Requires extra config |
| Resource usage | ~1GB RAM | ~200MB RAM | ~2GB RAM |
| License | MIT | Apache 2.0 | Apache 2.0 |
When to choose Authentik: You have 8+ services, need a proper admin UI for user management, want self-service enrollment with MFA, and plan to integrate LDAP or SCIM. For 2-3 services with basic auth-only needs, Authelia is lighter.
Prerequisites
- Traefik already deployed (see the Traefik reverse proxy guide)
- Docker and Docker Compose v2
- A domain pointed at your Traefik instance (e.g.,
auth.example.com) - PostgreSQL knowledge (Authentik requires a Postgres database)
- At least 2GB RAM free on the Docker host
Step 1 — Docker Compose Stack
Authentik consists of four components:
- Server — The core IdP, handles login, MFA, user management
- Worker — Background task processor (email, LDAP sync, event cleanup). Can scale horizontally.
- PostgreSQL — Primary database
- Redis — Cache, session storage, and task queue
|
|
.env File
|
|
Generate real credentials:
|
|
Replace the email and domain before deploying.
Deploy
|
|
Watch the logs for the first-time setup:
|
|
After about 30 seconds, Authentik is reachable at
https://auth.example.com. Log in with the bootstrap credentials
from your .env file.
Step 2 — Initial Configuration
After the first login, go through the initial setup wizard:
- Change the admin password — Immediately set a strong password
- Configure system settings — Under Admin Interface → System:
- Set the External host to
https://auth.example.com - Configure email if you need password reset flows
- Set the default token length (leave at 60)
- Set the External host to
- Create a default flow — Authentik uses “flows” for authentication, enrollment, and password reset. The default “default-authentication-flow” works for most setups.
First Login Flow
Navigate to https://auth.example.com — you see the Authentik login
portal. Enter your admin credentials, and you’re in the admin
interface.
The admin interface has two distinct areas:
- Admin Interface (
/if/admin/) — Full configuration, users, providers, flows, outposts - User Interface (
/if/user/) — Self-service portal for users to manage their own profile, MFA devices, and applications
Step 3 — Configure the Traefik Forward-Auth Middleware
Authentik uses an “outpost” — a lightweight component that proxies authentication requests. When deployed via Docker alongside the server, the outpost runs embedded within the server container. The forward-auth endpoint lives at:
http://authentik:9000/outpost.goauthentik.io/auth/traefik
Step 3a — Create a Proxy Provider in Authentik
- Go to Admin Interface → Applications → Providers
- Click Create, select Proxy Provider
- Configure:
- Name:
Traefik Forward Auth - Authentication flow:
default-authentication-flow - Authorization flow:
default-provider-authorization-implicit-consent - Mode:
Forward Auth (Single Application)
- Name:
- Save. Note the Client ID — you’ll need it for the provider.
Step 3b — Create an Application
- Go to Applications → Applications
- Click Create:
- Name:
Traefik Auth - Slug:
traefik-auth - Provider: Select the provider you just created
- Name:
- Save.
Step 3c — Define the Traefik Middleware
The forward-auth middleware lives in your Traefik dynamic
configuration. Add it to your middlewares.yml:
|
|
Important: The address uses http://authentik:9000 — this
assumes Authentik is on the same Docker network as Traefik. If
Authentik is on a separate network, use the container’s IP:
|
|
Then set address: http://10.0.20.30:9000/outpost.goauthentik.io/auth/traefik.
Step 3d — Add the Outpost Router Bypass
The forward-auth endpoint must NOT go through authentication itself
(that would create a loop). The outpost router we defined in the
docker-compose handles this — it routes
/outpost.goauthentik.io/* directly to Authentik without the
middleware:
|
|
This router has priority: 20 (higher than the default 0), so
requests to auth.example.com/outpost.goauthentik.io/* match this
route first and bypass the middleware.
Step 4 — Protect Services with Authentik
Now the fun part: add Authentik authentication to every service.
Grafana Example
|
|
Once added, visiting https://grafana.example.com redirects to
Authentik’s login portal. After successful login, you land on
Grafana. Repeat for every service.
Services That Need Exceptions
Some services have endpoints that must not go through Authentik:
Portainer — WebSocket connections for the terminal:
|
|
Grafana public dashboards:
|
|
Step 5 — Access Policies and Groups
Authentik’s policy engine is how you control who gets access to what.
Create Groups
- Go to Admin Interface → Directory → Groups
- Create:
- admins — Full access to admin services
- users — Standard user access
- readonly — View-only access to monitoring
Assign Users to Groups
- Go to Directory → Users
- Click a user → Groups tab → Join groups
Create Bindings Between Groups and Applications
Applications use “bindings” to control access. Each application can have policies that check group membership, user attributes, or time of day.
- Go to Applications → Applications → select your app
- Click the Policies / Bindings tab
- Click Create → select Group Binding
- Choose the group (e.g.,
admins) and set access mode togrant_allow
The ordering matters — first-match wins. Place deny rules before grant rules.
Expression Policies
For advanced controls, use expression policies:
|
|
|
|
Add these via Admin Interface → Policies → Expression Policy, then bind them to your applications.
Step 6 — Enabling MFA
Authentik supports TOTP (Google Authenticator, Authy), WebAuthn (passkeys, YubiKey), and Duo.
Default MFA Enrollment
- Go to Flows → Default Authentication Flow
- Add a Stage of type
authenticator_validateafter the password stage:- Device classes:
totp,webauthn - Not configured action:
configure - Last validation threshold:
days=30
- Device classes:
- Users are prompted to set up MFA on their next login
Require MFA for Specific Services
Create a binding that checks for MFA:
- Applications → select your app → Policies / Bindings
- Create → Expression Policy:
1 2 3 4 5 6 7# Must have at least one MFA device configured devices = request.user.authentik_events_user.get( pk=request.user.pk ).akstage_set.filter( stage_type="authenticator" ) return devices.exists() - Set mode to
grant_allowand order it before other bindings
MFA Without User Intervention
Users enrolled once via the user portal (/if/user/ →
Authenticator Devices) don’t need to re-enroll. The
last_validation_threshold in the flow stage determines how often
they need to re-verify their MFA token.
Step 7 — User Self-Service Portal
Authentik’s user interface at /if/user/ lets users:
- Change their password
- Enroll MFA devices (TOTP, WebAuthn)
- View their active sessions
- Access granted applications
- Update their profile
Forward the user portal through Traefik (same router as the admin interface, since they live under different paths).
Customizing the Login Page
Authentik supports custom branding:
- Go to Admin Interface → System → Branding
- Set:
- Title: Your homelab name
- Logo: URL to your logo (256x256 recommended)
- Favicon: URL to favicon
- Footer links: GitHub, status page, etc.
For deeper customization, place custom HTML/CSS/JS in the
custom-templates directory mounted in the Docker compose:
|
|
Templates use the Django template language. Override files in:
custom-templates/
├── login/
│ └── password.html # Password field template
├── flow/
│ └── loader.html # Flow loader screen
└── themes/
└── ... # CSS overrides
Step 8 — LDAP Outpost (Optional)
Authentik can act as an LDAP server for services that only support LDAP authentication (Proxmox, NAS devices, network appliances).
Enable the LDAP Outpost
- Go to Admin Interface → Applications → Outposts
- Click Create:
- Name:
LDAP Outpost - Type:
LDAP - Integrate with embedded outpost: Yes
- Name:
- Bind users and groups to the outpost
Add LDAP Port to the Server Container
Edit your docker-compose to expose LDAP ports:
|
|
Configure Service LDAP Binding
|
|
The bind credentials come from the Outpost settings page in the admin interface.
Step 9 — Backup Strategy
Authentik stores everything in PostgreSQL. Back up the database:
|
|
Also back up the .env file and the mounted media and certs
directories.
Restore Procedure
|
|
Troubleshooting
“Too many redirects” when visiting a protected service
The forward-auth endpoint is looping. Check:
- The outpost router has
PathPrefix(/outpost.goauthentik.io/)withpriority: 20(higher than the auth router’s default 0) - The
addressin the forward-auth middleware points to the correct container hostname/port - Authentik’s External host setting matches the domain
“401 Unauthorized” after login
The Token is invalid or expired. In Authentik admin:
- Applications → Providers → edit your proxy provider
- Re-generate the token
- Update the outpost if needed
WebSocket connections failing
Portainer terminal, Grafana live updates, and similar features use WebSockets. Authentik’s forward-auth does not support WebSocket upgrade natively. Create a bypass router:
|
|
LDAP connection refused
If you enabled the LDAP outpost and can’t connect:
- Verify the LDAP ports are exposed in docker-compose
- Check
docker compose logs serverfor LDAP errors - The outpost must have bindings to users/groups
Lost admin password
Reset it via the CLI:
|
|
The admin username is akadmin by default.
Putting It All Together — Reference Architecture
┌──────────────────────────────────────────────────────────┐
│ Internet / Cloudflare Tunnel │
│ ↓ │
│ Traefik → Authenticates via forward-auth middleware │
│ ↓ │
│ Authentik Outpost endpoint at auth.example.com │
│ ↓ │
│ Authentik validates → redirects to service │
│ ↓ │
│ Service receives user info via headers │
│ ↓ │
│ User lands on protected service, already authenticated │
└──────────────────────────────────────────────────────────┘
Request flow breakdown:
- User visits
https://grafana.example.com - Traefik’s
authentikforward-auth middleware intercepts the request - Traefik sends the request to
http://authentik:9000/outpost.goauthentik.io/auth/traefik - Authentik sees no session cookie → redirects to
auth.example.comlogin page - User logs in with credentials + MFA
- Authentik sets the
authentik_sessioncookie and redirects back to Traefik - Traefik retries the forward-auth check — this time Authentik returns 200 with user info headers
- Traefik forwards the original request with
X-authentik-*headers to Grafana - Grafana receives the authenticated user info in request headers
Summary
Authentik transforms a collection of independently-authenticated services into a unified, secure ecosystem. The key takeaways:
- Deploy with Docker Compose using PostgreSQL and Redis — allocate at least 2GB RAM and expose only port 9000 behind Traefik
- Configure the Traefik forward-auth middleware with the embedded outpost endpoint — one middleware file protects every service
- Protect services by adding
authentik@fileto their Traefik router middlewares — bypass WebSocket routes with a higher-priority router rule - Enforce MFA via flow stages — TOTP and WebAuthn with a
last_validation_thresholdof 30 days - Control access with group bindings — create admins, users, and readonly groups, then bind them to applications
- Extend with LDAP outpost for services that don’t support OIDC/OAuth2 — Proxmox, NAS appliances, and network gear
The investment in setting up Authentik pays off immediately. Instead of managing a dozen password databases and hoping users pick strong ones, you get a single identity source with MFA that every service inherits. For a homelab running 10+ web services, it’s not nice to have — it’s a security necessity.