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 Applications → Providers → Create
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).