👍 What we like
- ✓Centralized SSO with MFA for all services
- ✓Supports SAML, OAuth2/OIDC, and LDAP
- ✓Integrates seamlessly with Traefik forward auth
- ✓Open-source and self-hosted solution
👎 What to watch
- ✕Requires PostgreSQL and Redis dependencies
- ✕Needs at least 4 GB RAM and 2 vCPUs
- ✕Complex initial setup with multiple containers
📑 Contents ▾
- 01 Prerequisites
- 02 Step 1: Prepare the network and secrets
- 03 Step 2: Authentik’s docker-compose.yml
- 04 Step 3: Initial Authentik Configuration
- 05 Step 4: Create the forward auth provider and application
- 06 Step 5: Declare the forward auth middleware in Traefik
- 07 Step 6: Protect a demo service
- 08 Step 7: Hardening and best practices
- 09 Troubleshooting
- 10 Final verification
- 11 FAQ
- · What is the difference between Authentik and Authelia?
- · Does forward auth work with any service?
- · Can I use Authentik with Caddy or Nginx instead of Traefik?
- · How much resources does Authentik consume?
- · Is Authentik safe for production use?
- · How do I add a new service to SSO?
- 18 Related topics
You host about a dozen services on your server: a dashboard, Portainer, a monitoring tool, an admin panel. Some have no authentication, others have basic user management. Instead of hacking together a different basic_auth for each one, the best practice in 2026 is to place an Identity Provider (IdP) in front of everything, with a single login page, MFA, and centralized account management. This is the role of Authentik.
Authentik is a modern open-source IdP that speaks SAML, OAuth2/OIDC, LDAP, and, crucially, exposes a forward auth endpoint that Traefik can query before allowing a request through. In this tutorial, we deploy Authentik behind Traefik, configure forward auth, and protect a demo service behind a single SSO login page with two-factor authentication.
Prerequisites
- A secure VPS running Ubuntu 24.04 LTS, with at least 2 vCPUs and 4 GB of RAM (Authentik runs PostgreSQL, Redis, a server, and a worker). A Hetzner CPX21 or equivalent works well. If the server isn’t ready yet, see install and secure an Ubuntu VPS first.
- Docker and Docker Compose installed.
- Traefik v3 already deployed as a reverse proxy, with a Let’s Encrypt certificate resolver configured. We will recap the key points, but the full Traefik installation is beyond the scope of this tutorial.
- A domain name for which you control the DNS. We will use
auth.exemple.frfor Authentik andapp.exemple.frfor the protected service. - Ports 80 and 443 open in UFW.
Step 1: Prepare the network and secrets
Create a shared Docker network between Traefik, Authentik, and your services (if not already done):
docker network create proxy
Create the working directory and generate the secrets required by Authentik:
mkdir -p ~/authentik && cd ~/authentik
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env
The .env file now contains the PostgreSQL password and the Authentik secret key. Protect it:
chmod 600 .env
Step 2: Authentik’s docker-compose.yml
Create the composition file:
nano docker-compose.yml
services:
postgresql:
image: docker.io/library/postgres:16-alpine
container_name: authentik-postgres
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 30s
timeout: 5s
retries: 5
volumes:
- database:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${PG_PASS}
POSTGRES_USER: authentik
POSTGRES_DB: authentik
networks:
- internal
redis:
image: docker.io/library/redis:alpine
container_name: authentik-redis
restart: unless-stopped
command: --save 60 1 --loglevel warning
volumes:
- redis:/data
networks:
- internal
server:
image: ghcr.io/goauthentik/server:2026.2
container_name: authentik-server
restart: unless-stopped
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
volumes:
- media:/media
- templates:/templates
networks:
- internal
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.authentik.rule=Host(`auth.exemple.fr`)"
- "traefik.http.routers.authentik.entrypoints=websecure"
- "traefik.http.routers.authentik.tls.certresolver=letsencrypt"
- "traefik.http.services.authentik.loadbalancer.server.port=9000"
depends_on:
- postgresql
- redis
worker:
image: ghcr.io/goauthentik/server:2026.2
container_name: authentik-worker
restart: unless-stopped
command: worker
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
volumes:
- media:/media
- templates:/templates
- /var/run/docker.sock:/var/run/docker.sock
networks:
- internal
depends_on:
- postgresql
- redis
volumes:
database:
redis:
media:
templates:
networks:
internal:
proxy:
external: true
Key points:
- The
internalnetwork isolates PostgreSQL and Redis; onlyserveralso joins theproxynetwork to be reachable by Traefik. - The Traefik labels expose Authentik on
auth.exemple.frover HTTPS. Authentik’s internal port is 9000. - The
workerruns background tasks (email sending, session expiration); it does not need to be exposed.
Start the stack:
docker compose up -d
Step 3: Initial Authentik Configuration
On first startup, Authentik generates the administrator account via a wizard. Go to:
https://auth.exemple.fr/if/flow/initial-setup/
Set the administrator email and password (akadmin). You will then arrive at the admin dashboard. Before anything else, enable MFA on your account: Settings → MFA Devices → Enroll, and register a TOTP app (Aegis, Authenticator…). An IdP without MFA is hardly useful.
Step 4: Create the forward auth provider and application
Forward auth works like this: Traefik intercepts every request to a protected service, queries Authentik via a middleware, and only lets it through if the user is authenticated.
In the Authentik interface:
- Create a provider. Go to
Applications → Providers → Create, choose Proxy Provider. Select the Forward auth (single application) mode. Enter the external URLhttps://app.exemple.fr. Validate. - Create the application. In
Applications → Applications → Create, give it a name (“Demo”), a slug (demo), and associate the provider created in the previous step. - Bind the provider to the embedded outpost. Authentik provides an embedded outpost that handles forward auth requests. In
Applications → Outposts, edit theauthentik Embedded Outpostand add your “Demo” application to the list.
Step 5: Declare the forward auth middleware in Traefik
Add the Authentik middleware to Traefik’s dynamic configuration. If you are using a dynamic file, create it there:
http:
middlewares:
authentik:
forwardAuth:
address: "http://authentik-server:9000/outpost.goauthentik.io/auth/traefik"
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
The address points to Authentik’s embedded outpost on the proxy network. The authResponseHeaders transmit the authenticated user’s identity to the downstream service (useful for services that know how to read these headers).
Common pitfall: Traefik and Authentik must share the
proxynetwork, otherwise Traefik cannot resolveauthentik-server. Verify withdocker network inspect proxythat both containers are present.
Step 6: Protect a demo service
Deploy any service and apply the authentik middleware to it. In another folder:
services:
demo:
image: nginxdemos/hello
container_name: demo
restart: unless-stopped
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.demo.rule=Host(`app.exemple.fr`)"
- "traefik.http.routers.demo.entrypoints=websecure"
- "traefik.http.routers.demo.tls.certresolver=letsencrypt"
- "traefik.http.routers.demo.middlewares=authentik@file"
- "traefik.http.services.demo.loadbalancer.server.port=80"
networks:
proxy:
external: true
The decisive line is traefik.http.routers.demo.middlewares=authentik@file: it forces every request to app.exemple.fr to go through forward auth. The @file suffix indicates that the middleware comes from the file-based dynamic config (use @docker if it is defined by labels).
Start it:
docker compose up -d
Visit https://app.exemple.fr. You are redirected to the Authentik login page. After authentication (password + TOTP), you access the demo service. SSO is in place: a single login now protects all services bearing this middleware.
Step 7: Hardening and best practices
- Enforce MFA globally. In
Flows & Stages, modify the default authentication flow to make the TOTP step mandatory, not just optional. - Segment by groups. Create Authentik groups (admins, family, guests) and restrict access to each application via policies based on group membership.
- Limit session duration. Reduce the proxy provider’s
Session durationfor sensitive services. - Back up the database. All of Authentik’s state (users, providers, applications) lives in PostgreSQL. Schedule regular
pg_dumpof thedatabasevolume and export it off-site. Our tutorial automatic encrypted backup with restic and Backblaze applies directly to dumps. - Monitor attempts. Authentik logs every login attempt in
Events. Feed these logs into your monitoring to detect brute force attacks.
Troubleshooting
- Redirect loop to the login page. The application is not attached to the embedded outpost (step 4.3), or the provider’s external URL does not exactly match the service’s domain.
- 502 error on the protected service. Traefik cannot reach
authentik-server. Check the sharedproxynetwork and ensure the Authentik container is running (docker logs authentik-server). - “Forbidden” after authentication. A group policy is blocking the user. Check the application bindings in
Applications → your app → Policy / Group / User Bindings. - Authentik refuses to start. Often a PostgreSQL connection error: verify that
PG_PASSis identical across all services and that thepostgresqlcontainer ishealthy. - TOTP rejected in a loop. The VPS clock is drifting. Synchronize with
sudo timedatectl set-ntp true.
Final verification
# All Authentik containers are running
docker compose ps
# Authentik responds over HTTPS
curl -sI https://auth.exemple.fr/-/health/live/ | head -1
# The protected service redirects to login (302 to auth.exemple.fr)
curl -sI https://app.exemple.fr | head -3
FAQ
What is the difference between Authentik and Authelia?
Authentik is a full-featured IdP with a graphical interface, SAML/OIDC/LDAP support, and fine-grained user and flow management. Authelia is lighter, configured via YAML files, and excels at simple forward auth. Authentik is suitable if you also want to do OIDC for third-party apps; Authelia if you seek maximum simplicity. See our comparison Authentik vs Authelia vs Keycloak.
Does forward auth work with any service?
Yes, that’s the whole point: forward auth applies at the proxy level, upstream of the service. Even an application with no user management ends up protected by the Authentik login page. For deeper integration (real SSO with synchronized logout), prefer OIDC if the service natively supports it.
Can I use Authentik with Caddy or Nginx instead of Traefik?
Yes. Authentik exposes the same forward auth endpoints, which can be used by Caddy’s forward_auth or Nginx’s auth_request. The middleware configuration differs, but the principle is identical. To choose your proxy, consult Traefik vs Nginx Proxy Manager vs Caddy.
How much resources does Authentik consume?
The full stack (PostgreSQL, Redis, server, worker) runs comfortably with 1.5 to 2 GB of RAM at rest. The worker can spike during heavy tasks (LDAP sync, bulk email sending). For home or small team use, 4 GB of RAM offers a comfortable margin.
Is Authentik safe for production use?
Yes, it is a mature and actively maintained project, used in production by many organizations. Like any authentication entry point, it becomes critical: back up the database, enforce MFA, keep the image updated, and restrict access to the worker (which mounts the Docker socket).
How do I add a new service to SSO?
Three steps: create (or reuse) a proxy provider in forward auth mode with the correct external URL, create an application that references it, and attach this application to the embedded outpost. On the Traefik side, simply add the label middlewares=authentik@file to the new service’s router.
Related topics
- Authentik vs Authelia vs Keycloak: which self-hosted SSO in 2026
- Traefik vs Nginx Proxy Manager vs Caddy
- Automatic HTTPS reverse proxy with Caddy and Docker
- Automatic encrypted backup with restic and Backblaze
- Install and secure an Ubuntu VPS from A to Z
With Authentik in forward auth behind Traefik, you transform a collection of disparate services into a single-sign-on environment, protected by MFA and managed from a single interface. It is one of the most cost-effective security improvements you can make to a homelab. To stay updated on new authentication vulnerabilities and self-hosted tools, subscribe to our Telegram watch bot.