Skip to Content

Self-Host Authentik: The Modern Identity Provider for Your Homelab in 15 Minutes

Self-Host Authentik: The Modern Identity Provider for Your Homelab in 15 Minutes

Stop managing passwords across a dozen self-hosted apps. Deploy Authentik once, and give every service in your stack a single, secure login.

If you're running a homelab — Portainer, Nextcloud, Grafana, maybe a dozen other tools — you're probably juggling separate logins for each one. That's not just annoying; it's a security risk. Weak passwords get reused. Access control becomes a spreadsheet. And when someone leaves, you're manually disabling accounts across ten different UIs.

Authentik solves this. It's an open-source Identity Provider (IdP) that brings single sign-on (SSO), multi-factor authentication (MFA), and fine-grained access control to every app in your stack — whether it speaks OAuth2, SAML, LDAP, or just basic proxy authentication.

In this guide, you'll deploy Authentik with Docker Compose, configure your first application, and secure it behind a reverse proxy. No enterprise budget required.

---

What You'll Build

  • A fully functional Authentik instance with PostgreSQL and Redis
  • SSO-ready authentication for any app in your homelab
  • Admin dashboard for users, groups, and access policies
  • Optional: TOTP/WebAuthn MFA for every login

---

Prerequisites

| Requirement | Spec |

|-------------|------|

| VPS / Server | 2 vCPU, 4 GB RAM minimum |

| Storage | 10 GB free |

| Docker + Docker Compose | Installed and running |

| Reverse Proxy | Traefik or Nginx (recommended) |

| Domain | A subdomain pointed to your server (e.g., auth.yourdomain.com) |

---

Step 1: Create the Project Directory

mkdir -p ~/authentik && cd ~/authentik

---

Step 2: Docker Compose Configuration

Create docker-compose.yml:

version: "3.8"

services:

postgresql:

image: docker.io/library/postgres:16-alpine

restart: unless-stopped

healthcheck:

test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]

start_period: 20s

interval: 30s

retries: 5

timeout: 5s

volumes:

- database:/var/lib/postgresql/data

environment:

POSTGRES_PASSWORD: ${PG_PASS:?database password required}

POSTGRES_USER: ${PG_USER:-authentik}

POSTGRES_DB: ${PG_DB:-authentik}

env_file:

- .env

redis:

image: docker.io/library/redis:alpine

restart: unless-stopped

healthcheck:

test: ["CMD-SHELL", "redis-cli ping | grep PONG"]

start_period: 20s

interval: 30s

retries: 5

timeout: 3s

volumes:

- redis:/data

server:

image: ghcr.io/goauthentik/server:2024.8

restart: unless-stopped

command: server

environment:

AUTHENTIK_REDIS__HOST: redis

AUTHENTIK_POSTGRESQL__HOST: postgresql

AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}

AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}

AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}

AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}

AUTHENTIK_ERROR_REPORTING__ENABLED: "true"

volumes:

- ./media:/media

- ./custom-templates:/templates

- ./certs:/certs

env_file:

- .env

ports:

- "9000:9000"

- "9443:9443"

depends_on:

- postgresql

- redis

worker:

image: ghcr.io/goauthentik/server:2024.8

restart: unless-stopped

command: worker

environment:

AUTHENTIK_REDIS__HOST: redis

AUTHENTIK_POSTGRESQL__HOST: postgresql

AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}

AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}

AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}

AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}

user: root

volumes:

- /var/run/docker.sock:/var/run/docker.sock

- ./media:/media

- ./certs:/certs

- ./custom-templates:/templates

env_file:

- .env

depends_on:

- postgresql

- redis

volumes:

database:

driver: local

redis:

driver: local

---

Step 3: Environment Configuration

Create .env:

Database

PG_USER=authentik

PG_PASS=$(openssl rand -base64 36 | tr -d '\n')

PG_DB=authentik

Authentik Secret (generate a strong key)

AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')

Optional: Email for notifications

AUTHENTIK_EMAIL__HOST=smtp.gmail.com

AUTHENTIK_EMAIL__PORT=587

AUTHENTIK_EMAIL__USERNAME=

AUTHENTIK_EMAIL__PASSWORD=

AUTHENTIK_EMAIL__USE_TLS=true

[email protected]

Generate the secrets:

echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env

echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env

---

Step 4: Deploy

docker compose up -d

Wait for services to initialize (~30 seconds):

docker compose logs -f server

Look for: Booting worker with pid: — that means it's ready.

---

Step 5: Initial Setup

1. Navigate to http://your-server-ip:9000/if/flow/initial-setup/

2. Create your admin account

3. Log in to the admin dashboard at http://your-server-ip:9000

---

Step 6: Configure Your First Application (Example: Portainer)

1. In Authentik, go to ApplicationsProvidersCreate

2. Select OAuth2/OpenID Provider

3. Set:

- Name: portainer

- Authorization flow: default-provider-authorization-explicit-consent

- Client type: Confidential

- Client ID: (auto-generated, copy it)

- Client Secret: (auto-generated, copy it)

- Redirect URIs: https://portainer.yourdomain.com

4. Save, then create an Application linking to this provider

5. In Portainer:

- Settings → Authentication → OAuth

- Provider: Custom

- Authorization URL: https://auth.yourdomain.com/application/o/authorize/

- Token URL: https://auth.yourdomain.com/application/o/token/

- Resource URL: https://auth.yourdomain.com/application/o/userinfo/

- Logout URL: https://auth.yourdomain.com/application/o/portainer/end-session/

- Client ID / Secret: (from Authentik)

- Scopes: openid profile email

Done. Now Portainer delegates all logins to Authentik.

---

Step 7: Reverse Proxy (Traefik Example)

Add labels to the server service in docker-compose.yml:

labels:

- "traefik.enable=true"

- "traefik.http.routers.authentik.rule=Host(auth.yourdomain.com)"

- "traefik.http.routers.authentik.entrypoints=websecure"

- "traefik.http.routers.authentik.tls.certresolver=letsencrypt"

- "traefik.http.services.authentik.loadbalancer.server.port=9000"

---

Verification Checklist

  • [ ] Authentik dashboard loads at https://auth.yourdomain.com
  • [ ] Admin login works
  • [ ] Test application (Portainer/Nextcloud/Grafana) redirects to Authentik
  • [ ] Login succeeds, user info passes through
  • [ ] Logout from app clears Authentik session

---

Next Steps

  • Enable MFA: Go to Stages → Add TOTP or WebAuthn to your login flow
  • LDAP Outpost: Deploy the LDAP provider for apps that don't speak OAuth/SAML
  • Group Policies: Restrict app access by user groups
  • Event Logging: Monitor login attempts and failed authentications
  • Backup: docker exec authentik-postgresql-1 pg_dump -U authentik authentik > authentik-backup.sql

---

Related Guides

  • [Self-Host Portainer](/blog/portainer-guide) — Manage your Docker stack
  • [Self-Host CrowdSec](/blog/crowdsec-guide) — Add threat detection
  • [Self-Host Uptime Kuma](/blog/uptime-kuma-guide) — Monitor service health

---

Have questions? Drop a comment below or reach out on [Discord](https://discord.gg/sysbrix).
Self-Host Portainer: Manage All Your Docker Containers from One Dashboard in 15 Minutes
Deploy Portainer CE to manage Docker containers with a powerful web UI. Complete docker-compose setup, security hardening, and multi-environment management.