Authentik Locks Every Self-Hosted Service Behind One Password
Authentik has become the default identity provider for self-hosters in 2026, surpassing both Authelia and Keycloak. One Docker Compose file, five minutes of configuration, and every service you run shares the same login, the same MFA, and the same user directory.
By June 2026, Authentik has crossed 15,000 GitHub stars with a community doubling every year. Three years ago, the project was an underdog next to Keycloak and Authelia. Today, it’s the identity provider the self-hosting community recommends by default — and there’s a stack of reasons why.
If you run more than three self-hosted services, you know the pain: one account for Nextcloud, another for Grafana, a third for Gitea, a fourth for Jellyfin. Your Vaultwarden looks like a phone book. Authentik solves this permanently: one password, one MFA setup, and every service falls in line behind it.
A Full Identity Provider, Not a Thin Auth Proxy
Authentik is not a lightweight forward-auth daemon that checks HTTP headers. It’s a full IdP (Identity Provider) capable of speaking every protocol a modern infrastructure demands.
The stack runs on Python (Django) for the main server and Go for asynchronous workers. Storage is backed by PostgreSQL, with Redis handling caching and the message bus. The license is MPL 2.0 — weak copyleft, no commercial surprises.
The protocol coverage spans everything in production today:
- OAuth2 and OpenID Connect for modern applications (Grafana, Gitea, Nextcloud)
- SAML 2.0 for enterprise tools and legacy services
- LDAP for integration with existing directories or NAS appliances
- SCIM 2.0 for automated user provisioning and de-provisioning
- Proxy authentication for applications that support no standard at all — Authentik sits in front and injects identity into HTTP headers
MFA covers TOTP, WebAuthn (FIDO2 hardware keys), Duo, and static tokens. Everything is configurable per user, per group, or per application.
Auth Flows You Draw, Not Code
Where Keycloak buries you under nested configuration screens and Authelia demands YAML for every scenario, Authentik ships a visual flow designer. You chain stages — password verification, TOTP challenge, browser fingerprint check, group membership validation — as blocks on a canvas.
This model enables policies that are impossible elsewhere without custom code:
- Require MFA only from external networks, disable it over VPN
- Block access to sensitive applications if the user hasn’t changed their password in 90 days
- Redirect to a consent portal before first access to a new service
- Inject a risk verification step (geolocation, browser fingerprint) before granting admin access
A flow is a sequence of stages. A stage is a single unit. The combinations are unlimited — and the visual interface keeps you from losing the thread across three YAML files and a custom Nginx middleware block.
Docker Compose: Four Containers, One Directory
The official deployment uses Docker Compose with four services:
- server: the API and web UI (port 9000 HTTP, 9443 HTTPS)
- worker: asynchronous tasks (email delivery, cleanup, event processing)
- postgresql: the primary database
- redis: cache and message bus
The reference docker-compose.yml fits in about fifty lines:
services:
postgresql:
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${PG_PASS:?}
POSTGRES_USER: ${PG_USER:-authentik}
POSTGRES_DB: ${PG_DB:-authentik}
volumes:
- ./db:/var/lib/postgresql/data
redis:
image: docker.io/library/redis:alpine
restart: unless-stopped
command: --save 60 1 --loglevel warning
volumes:
- ./redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.12}
restart: unless-stopped
command: server
environment:
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?}
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS:?}
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_ERROR_REPORTING__ENABLED: "true"
volumes:
- ./media:/media
- ./custom-templates:/templates
ports:
- "9000:9000"
depends_on:
- postgresql
- redis
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.12}
restart: unless-stopped
command: worker
environment:
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?}
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS:?}
AUTHENTIK_REDIS__HOST: redis
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./media:/media
- ./certs:/certs
- ./custom-templates:/templates
depends_on:
- postgresql
- redis Two environment variables to generate before the first docker compose up -d:
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" > .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env Initial setup runs at http://<ip>:9000/if/flow/initial-setup/ to create the admin account. Then — immediately — put a reverse proxy in front (Nginx Proxy Manager, Caddy, Traefik) with Let’s Encrypt. An exposed port 9000 during setup is an open invitation to compromise: the admin account gets created over plain HTTP before you’ve configured anything.
Idle RAM consumption hovers around 500 MB — heavier than Authelia (50–100 MB) but dramatically lighter than Keycloak (1–2 GB minimum). For a typical homelab with 2 GB of RAM to spare, Authentik fits comfortably; Keycloak won’t even start.
The Proxy Provider: Magic for Apps Without Native SSO
The feature that tips the scales toward Authentik over Authelia is the built-in proxy provider. It works like a classic forward auth — Authentik sits between your reverse proxy and the application, checks the session, and passes or blocks the request — but it’s integrated into the same tool as your IdP.
You don’t need to deploy Authelia next to Keycloak just to cover both modern apps (OIDC/SAML) and legacy apps (header-based auth). Authentik handles both, in the same interface, with the same groups and policies.
The flow to protect Uptime Kuma or Portainer with Authentik:
- Create a Proxy Provider in the admin interface
- Set the application’s internal URL (
http://uptime-kuma:3001) - Create an Application referencing that provider
- Configure your reverse proxy to delegate authentication to Authentik (
/outpost.goauthentik.io)
Twenty minutes, stopwatch-timed. And the user sees a consistent login page — same theme, same MFA — regardless of which application sits behind it.
The Table That Settles It
The verdict is mechanical. Authelia wins if you have five services behind HTTP basic auth and just want a single login layer on top — YAML is enough, RAM is negligible, Go starts in two seconds. Keycloak wins if you manage 500+ users with Kerberos federations, complex SAML delegation chains, and compliance requirements that demand standardized audit trails.
For everything else — the 10-to-50-service homelab, the 5-to-50-developer team, the non-profit running Nextcloud and GitLab on donated hardware — Authentik hits the exact sweet spot. Light enough to run on an entry-level VPS, complete enough that you’ll never say “I’m missing a protocol,” modern enough that the interface isn’t punishment.
Deploy Authentik Before the Pain Sets In
The classic trap with an IdP is deploying it after you’ve accumulated fifteen services with fifteen separate accounts. Migration then becomes a nightmare: reconfigure every application to delegate authentication, merge existing accounts, manage the cutover without downtime.
The right strategy: deploy Authentik first, before the next service you add to your stack. Point new applications at the Authentik provider from day one. For existing services, migrate them one at a time, starting with the ones that natively support OIDC — Nextcloud, Grafana, Gitea, and Jellyfin all have documented integrations.
Total time for a full setup — installation, reverse proxy, first protected application — is under one hour. The return is instant: you never type a password twice again.