Authentik: Self-Hosted Identity Provider Setup Guide
PROGRAMMING LANGUAGES March 24, 2026, 11:30 a.m.

Authentik: Self-Hosted Identity Provider Setup Guide

Authentik is a powerful, open‑source identity provider (IdP) that lets you centralise authentication, authorisation, and user management for your cloud‑native stack. In this guide we’ll walk through every step needed to spin up a self‑hosted Authentik instance, configure it for common protocols, and integrate it with real‑world applications. By the end, you’ll have a production‑ready IdP that can handle SSO, MFA, and fine‑grained access control—all without relying on a third‑party service.

Why Choose Authentik?

Unlike many commercial IdPs, Authentik is fully open source, extensible, and designed to run on modest hardware. It supports OAuth2, OpenID Connect (OIDC), SAML 2.0, LDAP, and even SCIM for provisioning. This flexibility makes it a natural fit for developers who want to keep their authentication stack under their own control.

Another advantage is its modern UI built with Vue.js, which simplifies admin tasks like creating providers, mapping attributes, and reviewing audit logs. Plus, the built‑in policies engine lets you enforce conditional access based on groups, IP ranges, or device posture.

Prerequisites

Before diving in, make sure you have the following:

  • A Linux server (Ubuntu 22.04 LTS or Debian 12 are recommended) with at least 2 GB RAM and 2 CPU cores.
  • Docker Engine ≥ 20.10 and Docker Compose ≥ 2.0 installed.
  • A domain name pointing to your server’s public IP (e.g., auth.example.com).
  • Access to port 443 (HTTPS) and optionally port 80 for HTTP‑to‑HTTPS redirection.

If you prefer Kubernetes, you can swap the Docker Compose steps for a Helm chart later in the guide. For now, we’ll stick with Docker Compose because it’s the quickest way to get a sandbox up and running.

Step 1: Deploy Authentik with Docker Compose

Creating the Compose File

Start by creating a directory for your Authentik deployment and a docker-compose.yml file inside it. The following example uses the official Authentik images and sets up a PostgreSQL database for persistence.

# docker-compose.yml
version: "3.9"

services:
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: authentik
      POSTGRES_USER: authentik
      POSTGRES_PASSWORD: changeme   # ⚠️ Replace with a strong password
    volumes:
      - db-data:/var/lib/postgresql/data
    restart: unless-stopped

  authentik-server:
    image: ghcr.io/goauthentik/server:2024.2.2
    depends_on:
      - db
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: db
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: changeme   # Same as above
      AUTHENTIK_SECRET_KEY:  # 32‑byte base64 string, generate with `openssl rand -base64 32`
    ports:
      - "9000:9000"   # HTTP (optional, for local testing)
      - "9443:9443"   # HTTPS (recommended)
    volumes:
      - ./media:/media
      - ./templates:/templates
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    restart: unless-stopped

volumes:
  db-data:

Make sure to replace changeme with a secure password and generate a 32‑byte secret key. You can do that with:

openssl rand -base64 32

Save the key in an environment variable or a .env file and reference it in the compose file for better security.

Launching the Stack

Run the following command to pull the images and start the containers:

docker compose up -d

Docker will download the Authentik server, PostgreSQL, and Redis images, then spin up the services in the background. Verify everything is healthy with:

docker compose ps

You should see all three containers listed as “Up”. If any container restarts repeatedly, check the logs with docker compose logs <service> for clues.

Step 2: Initial Configuration via CLI

Creating the First Superuser

Authentik ships with a management CLI that lets you bootstrap the system. Execute the CLI inside the running container to create an admin account:

docker exec -it <container_id_or_name> /bin/bash
authentik-manage createsuperuser
# Follow the prompts:
# Email: admin@example.com
# Password: (choose a strong password)
# First name, last name: optional

The CLI also generates a default configuration file at /etc/authentik/config.yml. You can edit this file later to tweak settings such as token lifetimes or email backends.

Enabling HTTPS

Running Authentik behind HTTPS is non‑negotiable for production. The easiest way is to terminate TLS at a reverse proxy like Nginx or Traefik. Below is a minimal Nginx config that forwards traffic to the Authentik server’s internal port 9000 and automatically redirects HTTP to HTTPS.

# /etc/nginx/sites-available/authentik.conf
server {
    listen 80;
    server_name auth.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name auth.example.com;

    ssl_certificate     /etc/letsencrypt/live/auth.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/auth.example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

After placing the file, enable it with ln -s, reload Nginx, and verify you can reach https://auth.example.com/if/flow/redirect/ (the default login page).

Pro tip: Use Certbot to obtain free Let's Encrypt certificates. Run certbot --nginx -d auth.example.com and let it handle renewal automatically.

Step 3: Adding Your First Provider (OIDC)

Why OIDC?

OpenID Connect is the modern, JSON‑based protocol that powers Google Sign‑In, GitHub OAuth, and many SaaS platforms. By exposing an OIDC provider, Authentik can act as the identity source for any OIDC‑aware application.

We’ll create a provider for a demo Flask app, but the same steps apply to Kubernetes dashboards, Grafana, or any service that supports OIDC.

Creating the OIDC Provider in the UI

  1. Log in to the Authentik admin UI (usually https://auth.example.com/if/admin/).
  2. Navigate to Providers → OpenID Connect and click “Create”.
  3. Fill in the form:
    • Name: FlaskDemo
    • Redirect URIs: http://localhost:5000/oidc/callback
    • Client ID: leave blank to auto‑generate.
    • Client Secret: auto‑generated; copy it now.
  4. Save the provider. The UI will display the issuer URL (e.g., https://auth.example.com/application/o/flaskdemo/).

Flask Application Example

Below is a minimal Flask app that uses Authlib to authenticate via the Authentik OIDC provider we just created.

# app.py
from flask import Flask, redirect, url_for, session, request
from authlib.integrations.flask_client import OAuth

app = Flask(__name__)
app.secret_key = 'replace-with-a-secure-random-secret'

oauth = OAuth(app)

authentik = oauth.register(
    name='authentik',
    client_id='YOUR_CLIENT_ID',
    client_secret='YOUR_CLIENT_SECRET',
    server_metadata_url='https://auth.example.com/application/o/flaskdemo/.well-known/openid-configuration',
    client_kwargs={'scope': 'openid email profile'}
)

@app.route('/')
def index():
    user = session.get('user')
    if user:
        return f"Hello, {user['email']}!"
    return 'Login with Authentik'

@app.route('/login')
def login():
    redirect_uri = url_for('auth_callback', _external=True)
    return authentik.authorize_redirect(redirect_uri)

@app.route('/oidc/callback')
def auth_callback():
    token = authentik.authorize_access_token()
    user = authentik.parse_id_token(token)
    session['user'] = user
    return redirect('/')

if __name__ == '__main__':
    app.run(debug=True, port=5000)

Replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with the values you copied from the Authentik UI. Run the app with python app.py and visit http://localhost:5000. Clicking “Login with Authentik” will redirect you to the Authentik login page, and upon successful authentication you’ll be back in Flask with the user’s email displayed.

Step 4: Configuring SAML 2.0 for Enterprise Apps

When to Use SAML

SAML remains the de‑facto standard for many legacy enterprise applications (e.g., Microsoft SharePoint, ServiceNow, or custom Java portals). Authentik’s SAML provider can act as an Identity Provider (IdP) that issues assertions to these Service Providers (SP).

Let’s set up a SAML provider for a generic SP that expects a NameID in email format and includes the groups attribute.

Creating the SAML Provider

  1. In the Authentik UI, go to Providers → SAML and click “Create”.
  2. Enter a descriptive name, e.g., EnterpriseSP.
  3. Set Entity ID to your SP’s identifier (often a URL like https://sp.example.com/metadata).
  4. Upload the SP’s metadata XML file or paste the XML directly.
  5. Under “Attribute Mapping”, map email to NameID and add a custom attribute groups that pulls from the user’s group memberships.
  6. Save the provider and note the IdP metadata URL (e.g., https://auth.example.com/application/saml2/enterprise-sp/metadata).

Testing with a SAML Test Tool

You can validate the configuration using SAMLTest.id. Register the IdP metadata URL, then initiate a login from the test portal. If everything is wired correctly, you’ll see a successful authentication with the expected attributes.

Pro tip: Enable Signed Assertions and Encrypted Assertions for production deployments. This protects user data in transit and satisfies compliance requirements like GDPR and HIPAA.

Step 5: Managing Users, Groups, and Policies

Importing Users via SCIM

SCIM (System for Cross‑Domain Identity Management) is ideal for bulk provisioning from HR systems or Azure AD. Authentik provides a built‑in SCIM endpoint that can be consumed by external tools.

To enable SCIM, create a “SCIM Provider” in the UI, assign it a token, and use the following endpoint format:

https://auth.example.com/scim/v2/

Then, from a Python script you can push users like this:

import requests, json

SCIM_TOKEN = 'your-scim-token'
HEADERS = {
    'Authorization': f'Bearer {SCIM_TOKEN}',
    'Content-Type': 'application/json'
}
USER_PAYLOAD = {
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "jdoe",
    "name": {"givenName": "John", "familyName": "Doe"},
    "emails": [{"value": "jdoe@example.com", "primary": True}],
    "active": True
}

resp = requests.post(
    'https://auth.example.com/scim/v2/Users',
    headers=HEADERS,
    data=json.dumps(USER_PAYLOAD)
)

print(resp.status_code, resp.json())

The response will contain the newly created user’s ID, which you can later reference for group assignments or attribute updates.

Group‑Based Access Policies

Authentik’s policy engine lets you define rules that evaluate user attributes, groups, and request context. For example, you might want to restrict access to a “Finance Dashboard” to members of the finance group and only from corporate IP ranges.

  1. Create a group called finance under Groups → Create.
  2. Navigate to Policies → Create and select “Expression Policy”.
  3. Enter an expression like:
    user.is_in_group('finance') and request.ip in ['10.0.0.0/8']
  4. Attach this policy to the provider (e.g., the OIDC app) under “Access Policies”.

When a user attempts to authenticate, Authentik evaluates the expression. If the condition fails, the login is denied with a clear error message.

Step 6: Enabling Multi‑Factor Authentication (MFA)

Supported MFA Methods

Authentik supports TOTP (Google Authenticator, Authy), WebAuthn (FIDO2 security keys), and backup codes. Enabling MFA adds an extra layer of security, especially for admin accounts and privileged users.

To activate MFA globally, go to Settings → Authentication → MFA Settings** and toggle the “Require MFA for all users” switch. You can also enforce MFA per‑policy using the same expression language we saw earlier.

Configuring TOTP for a User

When a user logs in for the first time after MFA is required, Authentik will present a QR code. The user scans it with their authenticator app, which then generates time‑based codes. The user must also download a set of backup codes for recovery.

Pro tip: Encourage users to register a WebAuthn device (e.g., YubiKey) as a primary factor. WebAuthn is phishing‑resistant and provides a seamless login experience on modern browsers.

Step 7: Monitoring, Logging, and Backups

Collecting Logs with Loki

Authentik

Share this article