Authentik Self-Hosted SSO: Identity Provider for the Homelab

By LK Wood IV · 2026-06-01 · ~15 min read · St. Louis County, MO

Authentik self-hosted SSO architecture: a browser reaches Nginx Proxy Manager over HTTPS at auth.yourdomain.com, which forwards to the authentik-server container on port 9000. The server and worker containers share a PostgreSQL 16 database and a Redis cache (about 420 MB idle across four containers), connecting apps like Nextcloud over OIDC and BookStack over LDAP on port 3389.

Once you have ten self-hosted services running, the per-app account problem becomes real. Nextcloud has one username/password. BookStack has another. Portainer has a third. Grafana has a fourth. If you add family members or collaborators, you’re creating accounts across every app separately.

Authentik solves this with a single login that every other app delegates to. It runs in Docker, supports every authentication protocol your apps need, and the free tier covers everything a homelab will ever use.

What Authentik gives you

  • Single sign-on (SSO): one login for Nextcloud, BookStack, Grafana, Portainer, Gitea, Immich, and any other OIDC/SAML/LDAP-capable app
  • LDAP provider: apps that can’t do OIDC (or are easier to configure with LDAP) connect via Authentik’s built-in LDAP server
  • MFA: TOTP, WebAuthn/passkeys, Duo — configurable per application and per user group
  • User self-enrollment: users can reset their own passwords, enroll MFA devices, and manage sessions through the Authentik user portal
  • Outpost proxy: protect apps that have no built-in auth at all (add authentication in front of any web UI)

The Authentik model

Before deploying, understand three concepts:

Providers: define the protocol connection — OIDC/OAuth2, SAML, LDAP, or Proxy. Each external app needs a Provider with the right protocol for how it authenticates.

Applications: tie a Provider to an entry in the Authentik portal (name, icon, launch URL). Users see a list of Applications in their portal; clicking an Application authenticates them to that service.

Flows: sequences of stages (authentication prompts, MFA, consent, enrollment) that run when a user logs in, enrolls, or resets their password. Authentik ships with sensible default flows.

Stack requirements

Authentik has more dependencies than most self-hosted apps:

ContainerRole
authentik-serverMain web UI, API, authentication flows
authentik-workerBackground tasks (email, cleanup, LDAP outpost)
authentik-dbPostgreSQL — user accounts, sessions, configuration
authentik-redisTask queue and cache

Total idle RAM: approximately 500–700 MB combined. Authentik is heavier than BookStack or Paperless-ngx at idle, which reflects the complexity of the task it handles.

Directory layout

mkdir -p /opt/authentik/media /opt/authentik/certs /opt/authentik/custom-templates

Docker Compose

services:
  authentik-db:
    image: postgres:16
    container_name: authentik-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: authentik
      POSTGRES_USER: authentik
      POSTGRES_PASSWORD: CHANGE_THIS_DB_PASSWORD
    volumes:
      - /opt/authentik/db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U authentik"]
      interval: 10s
      timeout: 5s
      retries: 5

  authentik-redis:
    image: redis:7-alpine
    container_name: authentik-redis
    restart: unless-stopped
    command: --save 60 1 --loglevel warning

  authentik-server:
    image: ghcr.io/goauthentik/server:2024.12
    container_name: authentik-server
    restart: unless-stopped
    command: server
    depends_on:
      authentik-db:
        condition: service_healthy
      authentik-redis:
        condition: service_started
    environment:
      AUTHENTIK_REDIS__HOST: authentik-redis
      AUTHENTIK_POSTGRESQL__HOST: authentik-db
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: CHANGE_THIS_DB_PASSWORD
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_SECRET_KEY: CHANGE_THIS_SECRET_KEY
      AUTHENTIK_EMAIL__HOST: smtp.yourdomain.com
      AUTHENTIK_EMAIL__PORT: 587
      AUTHENTIK_EMAIL__USE_TLS: "true"
      AUTHENTIK_EMAIL__USERNAME: authentik@yourdomain.com
      AUTHENTIK_EMAIL__PASSWORD: your-smtp-password
      AUTHENTIK_EMAIL__FROM: authentik@yourdomain.com
    volumes:
      - /opt/authentik/media:/media
      - /opt/authentik/custom-templates:/templates
    ports:
      - "9000:9000"
      - "9443:9443"

  authentik-worker:
    image: ghcr.io/goauthentik/server:2024.12
    container_name: authentik-worker
    restart: unless-stopped
    command: worker
    depends_on:
      authentik-db:
        condition: service_healthy
      authentik-redis:
        condition: service_started
    environment:
      AUTHENTIK_REDIS__HOST: authentik-redis
      AUTHENTIK_POSTGRESQL__HOST: authentik-db
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: CHANGE_THIS_DB_PASSWORD
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_SECRET_KEY: CHANGE_THIS_SECRET_KEY
    volumes:
      - /opt/authentik/media:/media
      - /opt/authentik/custom-templates:/templates
      - /var/run/docker.sock:/var/run/docker.sock

Three values to set before starting:

  • AUTHENTIK_SECRET_KEY: generate with openssl rand -hex 32
  • AUTHENTIK_POSTGRESQL__PASSWORD and POSTGRES_PASSWORD: must match
  • SMTP settings: required for password reset and email verification flows; without SMTP, those flows fail silently

Pinning the version: use a specific version tag (2024.12) rather than latest. Authentik uses a YEAR.MONTH release format; major updates can change configuration and database schema. Check release notes before updating.

First start

cd /opt/authentik
docker compose up -d

# Watch the server start (takes 60-90 seconds first run for database migration)
docker compose logs -f authentik-server

Wait for the log line Starting web server before navigating to the UI.

Initial admin setup: navigate to https://your-host-ip:9443/if/flow/initial-setup/ — this URL only works on the first run. Create the admin account here. After setup, the initial-setup flow is disabled.

Reverse proxy with NPM

Add Authentik to Nginx Proxy Manager:

  • Domain: auth.yourdomain.com
  • Forward to: authentik-server:9000
  • SSL: Let’s Encrypt

In NPM Advanced tab:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
client_max_body_size 10M;

Update AUTHENTIK_URL in your compose environment to https://auth.yourdomain.com after setting up the proxy. Authentik uses this URL in redirect URIs for OAuth2 flows.

Configure your first OIDC application: Nextcloud

Nextcloud is one of the best test applications for Authentik because it has mature OIDC support. This also fills in your user accounts with a real test.

Step 1: Create an OIDC Provider in Authentik

  1. Authentik Admin → Applications → Providers → Create
  2. Select: OAuth2/OpenID Connect Provider
  3. Name: Nextcloud
  4. Client ID: auto-generated (copy for later)
  5. Client Secret: auto-generated (copy for later)
  6. Redirect URIs: https://nextcloud.yourdomain.com/apps/oidc_login/oidc (exact URL for the Nextcloud OIDC app)
  7. Sub Mode: Based on username (default is fine)
  8. Save

Step 2: Create an Application

  1. Admin → Applications → Applications → Create
  2. Name: Nextcloud
  3. Provider: select Nextcloud (from step 1)
  4. Launch URL: https://nextcloud.yourdomain.com
  5. Icon: upload a Nextcloud logo (optional)
  6. Save

Step 3: Configure Nextcloud

In Nextcloud:

  1. Install the oidc_login app via Nextcloud → Apps → search “OpenID Connect Login”
  2. Add to config/config.php:
'oidc_login_provider_url' => 'https://auth.yourdomain.com/application/o/nextcloud/',
'oidc_login_client_id' => 'CLIENT_ID_FROM_AUTHENTIK',
'oidc_login_client_secret' => 'CLIENT_SECRET_FROM_AUTHENTIK',
'oidc_login_auto_redirect' => false,
'oidc_login_button_text' => 'Log in with Authentik',
'oidc_login_scope' => 'openid email profile',
'oidc_login_end_session_redirect' => false,

After adding the config, Nextcloud shows an “Authentik” button on the login page. Clicking it redirects to Authentik, authenticates, and returns to Nextcloud with the user session.

Configure BookStack with LDAP

BookStack’s SAML2 and LDAP support are both good. LDAP is simpler to configure and doesn’t require understanding SAML assertion mapping. Authentik’s built-in LDAP provider serves BookStack accounts directly.

Step 1: Create an LDAP Provider in Authentik

  1. Admin → Applications → Providers → Create → LDAP Provider
  2. Name: LDAP
  3. Bind Flow: default
  4. Search Group: create a group called homelab-ldap — all users in this group are visible over LDAP
  5. Save

Step 2: Create an Application for the LDAP Provider

  1. Admin → Applications → Applications → Create
  2. Name: LDAP
  3. Provider: select LDAP
  4. No Launch URL needed — LDAP isn’t a browser flow
  5. Save

Step 3: Create an LDAP Outpost

  1. Admin → Applications → Outposts → Create
  2. Name: LDAP Outpost
  3. Type: LDAP
  4. Select the LDAP Application
  5. Save

The LDAP Outpost binds to port 3389 on the Authentik worker container (or a dedicated outpost container for more advanced setups). For a simple homelab setup, the embedded outpost (running inside the worker) is sufficient.

Step 4: Configure BookStack

In your BookStack Docker Compose environment:

AUTH_METHOD: ldap
LDAP_SERVER: authentik-worker
LDAP_PORT: 3389
LDAP_BASE_DN: "DC=ldap,DC=goauthentik,DC=io"
LDAP_DN: "cn=ldapservice,DC=ldap,DC=goauthentik,DC=io"
LDAP_PASS: your-authentik-service-account-password
LDAP_USER_FILTER: "(&(objectClass=person)(uid={user}))"
LDAP_FOLLOW_REFERRALS: "false"

The LDAP_BASE_DN format is Authentik’s internal LDAP tree. The LDAP_DN is a bind user — create a service account in Authentik for this purpose (a user with a known password that BookStack uses to search the LDAP directory).

Add MFA for specific applications

Authentik’s MFA is configured per-flow, not per-user. To require TOTP for all logins:

  1. Admin → Flows & Stages → Stages → Create → Authenticator TOTP Stage
  2. Add a Stage Binding in the default authentication flow after the password stage

To require MFA only for specific applications (e.g., Proxmox access but not BookStack):

  1. Create a new authentication flow specifically for high-security apps
  2. Include the MFA stage in that flow
  3. Configure the Proxmox Application to use this high-security flow instead of the default

This is where Authentik’s model shows its depth — granular security policies without per-app code.

User management

Create users: Admin → Directory → Users → Create

Or enable self-enrollment: Admin → Flows → create an enrollment flow and bind it to your Authentik tenant.

User groups: Admin → Directory → Groups → Create

Groups control which Applications users can access. Create groups per tier of access (e.g., homelab-admin, homelab-read, family) and configure Application policy to allow specific groups.

Password reset: Authentik ships with a recovery flow by default. Users navigate to the Authentik login page, click “Forgot password,” and receive an email with a reset link. This requires SMTP configuration.

Backup

Authentik’s data lives in PostgreSQL. Back up with:

docker compose exec authentik-db pg_dump -U authentik authentik \
  > /opt/authentik/backup/authentik-$(date +%Y%m%d).sql

Also back up /opt/authentik/media/ — this contains uploaded files (icons, certificates).

For encrypted LDAP connections or custom TLS certificates, back up /opt/authentik/certs/ as well.

Resource usage

ContainerIdle RAM
authentik-server~200 MB
authentik-worker~150 MB
authentik-db~60 MB
authentik-redis~10 MB
Total~420 MB

Peak RAM during login storms or during MFG enrollment flows can reach 600–700 MB combined. For a homelab with 16+ GB RAM, this is negligible.

Updating Authentik

Authentik updates can include database migrations. Always check the release notes before updating a major version (e.g., 2024.10 → 2024.12).

# Update the version in your compose file first
# Then:
docker compose pull
docker compose up -d
docker compose logs -f authentik-server

Watch for any migration errors in the server log on startup. Authentik handles migrations automatically on startup; no manual migration command needed for minor updates.


Authentik connects to the other services in the self-hosted stack. The Nextcloud AIO setup guide covers the Nextcloud side of OIDC integration. The BookStack Docker guide covers LDAP configuration for BookStack users. The Vaultwarden guide covers the password manager you’ll want for managing all your service credentials before SSO replaces per-service logins. The Nginx Proxy Manager guide covers the HTTPS reverse proxy that Authentik requires. For external access via Tailscale, the Tailscale guide covers connecting all services over the same WireGuard mesh.

Frequently asked questions

What is Authentik and what does it replace?
Authentik is an open-source Identity Provider (IdP) that handles authentication and authorization for other applications. It replaces cloud identity services like Okta, Azure AD B2C, or Auth0 in a homelab context. With Authentik, users log into one place (the Authentik portal) and get seamless access to Nextcloud, BookStack, Vaultwarden, Portainer, Grafana, and any other app that supports OIDC, SAML, LDAP, or OAuth2. One account per user across your entire self-hosted stack.
Does Authentik require a domain and SSL?
Yes. Authentik requires HTTPS — it will not function correctly over plain HTTP in production. You need a domain (or at minimum a local hostname) with a valid TLS certificate. Nginx Proxy Manager with Let’s Encrypt is the typical setup: point a subdomain (e.g., auth.yourdomain.com) at Authentik’s port and issue a certificate. For purely local use without a public domain, you can use a self-signed certificate and accept the browser warning, but OIDC flows in some apps reject self-signed certs.
What apps can Authentik connect to?
Any app that supports OIDC, OAuth2, SAML 2.0, LDAP, or a proxy authentication header. Common homelab integrations: Nextcloud (OIDC), BookStack (LDAP or SAML), Grafana (OIDC), Portainer (OAuth2), Proxmox (OIDC with realm configuration), Gitea (OIDC), Minio (OIDC), Immich (OIDC), and Vaultwarden (SSO via OIDC on the paid Bitwarden client, though the free client requires direct login). The Authentik documentation maintains a library of provider-specific integration guides.
Is Authentik hard to set up?
The initial deploy is straightforward: five environment variables and a Docker Compose file. The learning curve is in understanding Authentik’s model (Applications, Providers, Flows, Policies) before you can connect your first app. Allow 30–60 minutes to get the stack running and connect one test application. Once you understand the model, each additional app takes 5–10 minutes to configure.
What is the difference between an Authentik Application and a Provider?
A Provider defines the protocol and configuration for how an external app connects to Authentik (OIDC, SAML, LDAP). An Application ties a Provider to display metadata (name, icon, URL) and applies access policies. To add a new service: create a Provider for the protocol it supports, create an Application that uses that Provider, and configure the service with the credentials the Provider generated. You can reuse a single Provider across multiple Applications if needed, or create one Provider per Application.
Does Authentik have multi-factor authentication?
Yes. Authentik supports TOTP (authenticator apps), WebAuthn (hardware security keys and passkeys), Duo, and email verification as MFA stages. You configure MFA requirements per-flow — you can require MFA only for certain applications (e.g., require MFA for Proxmox access but not for Grafana read-only dashboards) or enforce it globally for all logins. Device enrollment is per-user in the Authentik self-service portal.