This guide covers deploying Authentik using either Dockhand or the Docker Compose CLI with the same files.
- Ubuntu 24.04 VM with Docker installed
- Dockhand (if using the GUI method) or terminal access for the CLI method
- Nginx Proxy Manager with a wildcard SSL certificate
- A chosen subdomain (e.g.
auth.yourdomain.com)
Dockhand is a modern Docker management UI — free for homelabs, with OIDC/SSO included at no cost. If you plan to use Method 1 (GUI deployment), install Dockhand first.
# dockhand/docker-compose.yml
services:
dockhand:
image: fnsys/dockhand:latest
container_name: dockhand
restart: unless-stopped
ports:
- 3000:3000
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- dockhand_data:/app/data
volumes:
dockhand_data:docker compose up -ddocker run -d \
--name dockhand \
--restart unless-stopped \
-p 3000:3000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v dockhand_data:/app/data \
fnsys/dockhand:latestservices:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: dockhand
POSTGRES_PASSWORD: changeme
POSTGRES_DB: dockhand
volumes:
- postgres_data:/var/lib/postgresql/data
dockhand:
image: fnsys/dockhand:latest
restart: unless-stopped
ports:
- 3000:3000
environment:
DATABASE_URL: postgres://dockhand:changeme@postgres:5432/dockhand
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- dockhand_data:/app/data
depends_on:
- postgres
volumes:
postgres_data:
dockhand_data:After deploying, open http://localhost:3000 (or your VM's IP) to complete initial setup. Put it behind NPM with SSL for production use.
For managing Docker hosts behind NAT or a firewall, Dockhand uses the open-source Hawser agent — see the Dockhand docs for multi-host setup.
On your Ubuntu VM, generate the required secrets:
# Generate PostgreSQL password
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')"
# Generate Authentik secret key
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')"Copy these values — you'll need them when creating the stack in Dockhand.
- Log into Dockhand
- Navigate to Stacks → New Stack
- Name:
authentik - Paste the entire
docker-compose.ymlcontent into the editor
Add the following in the stack's environment variable section:
Required:
PG_PASS=<paste-your-generated-password>
AUTHENTIK_SECRET_KEY=<paste-your-generated-secret>
Optional (defaults shown):
PG_USER=authentik
PG_DB=authentik
AUTHENTIK_ERROR_REPORTING__ENABLED=false
Email (if configuring — Fastmail example):
AUTHENTIK_EMAIL__HOST=smtp.fastmail.com
AUTHENTIK_EMAIL__PORT=587
AUTHENTIK_EMAIL__USERNAME=your-email@fastmail.com
AUTHENTIK_EMAIL__PASSWORD=your-app-specific-password
AUTHENTIK_EMAIL__USE_TLS=true
AUTHENTIK_EMAIL__FROM=authentik@yourdomain.com
Fastmail: Use an app-specific password generated under Settings → Privacy & Security → Connected Apps & API Tokens. Do not use your main account password.
- Click Deploy
- Wait 2–3 minutes for all containers to start and become healthy
- Check container logs for errors
- Confirm all 4 containers (postgresql, redis, server, worker) are running and healthy
mkdir -p /opt/authentik
cd /opt/authentik
# Copy or clone docker-compose.yml and env.template hereBefore deploying, review docker-compose.yml and update the following to match your setup:
AUTHENTIK_HOST— set to your public Authentik URL (e.g.https://auth.yourdomain.com) in bothserverandworkerAUTHENTIK_CSRF_TRUSTED_ORIGINS— add your AWS SSO region endpoint if using AWS Identity Center (e.g.https://us-east-1.sso.signin.aws); present in bothserverandworker- Volume paths — the compose file uses relative
./data,./media,./certs, and./custom-templatespaths by default; bind-mount alternatives pointing to absolute host paths (e.g./opt/authentik/data) are included as commented lines alongside each volume entry AUTHENTIK_TAG— the image version is pinned to2026.2.1and controlled via.env; updateAUTHENTIK_TAGin your.envfile when upgrading
cd /opt/authentik
cp env.template .env
# Generate and insert secrets
PG_PASS=$(openssl rand -base64 36 | tr -d '\n')
AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')
sed -i "s/REPLACE_WITH_GENERATED_PASSWORD/${PG_PASS}/" .env
sed -i "s/REPLACE_WITH_GENERATED_SECRET/${AUTHENTIK_SECRET_KEY}/" .env
# Verify
cat .envOr generate and write manually:
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .envenv.template includes pre-commented email configuration blocks for Fastmail, Gmail, Office 365, and SendGrid. Open .env and uncomment the block for your provider rather than typing the variables from scratch:
nano .envFastmail example:
AUTHENTIK_EMAIL__HOST=smtp.fastmail.com
AUTHENTIK_EMAIL__PORT=587
AUTHENTIK_EMAIL__USERNAME=your-email@fastmail.com
AUTHENTIK_EMAIL__PASSWORD=your-app-specific-password
AUTHENTIK_EMAIL__USE_TLS=true
AUTHENTIK_EMAIL__FROM=authentik@yourdomain.com
Fastmail: Generate an app-specific password under Settings → Privacy & Security → Connected Apps & API Tokens. Port 587 with STARTTLS is recommended. Port 465 with SSL/TLS is also supported — use
AUTHENTIK_EMAIL__USE_SSL=trueandAUTHENTIK_EMAIL__PORT=465in that case.
cd /opt/authentik
docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f- Log into NPM
- Go to Proxy Hosts → Add Proxy Host
| Setting | Value |
|---|---|
| Domain Names | auth.yourdomain.com |
| Scheme | http |
| Forward Hostname/IP | your VM's LAN IP |
| Forward Port | 9000 |
| Cache Assets | ✅ |
| Block Common Exploits | ✅ |
| Websockets Support | ✅ |
| Setting | Value |
|---|---|
| SSL Certificate | your wildcard certificate |
| Force SSL | ✅ |
| HTTP/2 Support | ✅ |
| HSTS Enabled | ✅ |
Click Save and wait 10–15 seconds.
-
Navigate to:
https://auth.yourdomain.com/if/flow/initial-setup/⚠️ The trailing slash is required. -
Set a password for the
akadminuser -
Log in:
- Username:
akadmin - Password: what you just set
- Username:
-
Go to Admin Interface → System → Settings
- Set Authentik Domain:
https://auth.yourdomain.com - Click Save
- Set Authentik Domain:
To use Authentik as a SAML/OIDC identity provider with AWS Identity Center, AUTHENTIK_CSRF_TRUSTED_ORIGINS must include your AWS SSO sign-in endpoint. This is required in both the server and worker services:
AUTHENTIK_CSRF_TRUSTED_ORIGINS: "https://auth.yourdomain.com,https://us-east-1.sso.signin.aws"Replace us-east-1 with the AWS region your Identity Center instance is configured in. Without this, SAML and OIDC flows initiated from the AWS console will fail with CSRF verification errors.
After updating, restart both services:
docker compose restart server workerDockhand: view container status and health directly in the stack view.
CLI:
docker compose ps
# All 4 containers should show as "Up" and "healthy"# All services
docker compose logs -f
# Specific service
docker compose logs -f server
docker compose logs -f worker
docker compose logs -f postgresql
docker compose logs -f redis# Confirm port 9000 is listening
ss -tlnp | grep 9000
# Quick test
curl -sI http://localhost:9000
# Expect: HTTP/1.1 302 Found (redirect to /if/flow/default-authentication-flow/)Use the Dockhand stack controls to start, stop, restart, and view logs. The exec/console feature provides shell access if needed.
cd /opt/authentik
docker compose stop # stop all services
docker compose start # start stopped services
docker compose restart # restart all services
docker compose down # stop and remove containers (data preserved)
docker compose down -v # stop, remove containers AND volumes — deletes data
docker compose pull # pull latest images
docker compose up -d # start (or update after pull)Restart a single service:
docker compose restart server
docker compose restart workercp .env .env.backup
# Store this file securely — it contains your database password and secret key
# Consider encrypting: gpg -c .env.backup# Backup
docker exec authentik-postgresql pg_dump -U authentik authentik \
> authentik-backup-$(date +%Y%m%d).sql
# Restore
cat authentik-backup-YYYYMMDD.sql | \
docker exec -i authentik-postgresql psql -U authentik -d authentik# List Authentik volumes
docker volume ls | grep authentik
# Backup media volume
docker run --rm \
-v authentik-media:/data \
-v $(pwd):/backup \
alpine tar czf /backup/authentik-media-$(date +%Y%m%d).tar.gz -C /data .
# Restore media volume
docker run --rm \
-v authentik-media:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/authentik-media-YYYYMMDD.tar.gz -C /data- Confirm containers are running:
docker compose ps - Check port 9000 is listening:
ss -tlnp | grep 9000 - Verify the correct VM IP is set in NPM
- Check firewall — NPM must be able to reach the VM on port 9000
- Check NPM logs — connection refused vs timeout point to different root causes
AUTHENTIK_CSRF_TRUSTED_ORIGINSmust be set in bothserverandworker- The value must include the exact
https://origin — no trailing slashes - Check your Identity Center region matches the URL:
https://<region>.sso.signin.aws - After any change:
docker compose restart server worker
docker compose logs postgresql
docker compose logs redis
docker compose logs serverCommon causes:
- Missing or malformed
PG_PASSorAUTHENTIK_SECRET_KEY - Port 9000 or 9443 already in use on the host
- Redis not healthy before server/worker attempt to start
docker exec authentik-server env | grep AUTHENTIK
docker exec authentik-server env | grep PGIf variables are missing, confirm .env exists in the same directory as docker-compose.yml and re-run docker compose up -d.
- URL must have trailing slash:
/if/flow/initial-setup/ - Wait at least 60 seconds after first deploy — Authentik takes time to fully initialize
- Check for errors:
docker compose logs -f server
- Confirm you are using an app-specific password, not your Fastmail account password
AUTHENTIK_EMAIL__USERNAMEmust be your full Fastmail address (you@fastmail.com)- Port 587 +
USE_TLS=true(STARTTLS) or port 465 +USE_SSL=true(SSL/TLS) - Send a test email from Admin Interface → System → Email
- Never commit
.envto version control — add.envto.gitignore - Use strong randomly generated values for
PG_PASSandAUTHENTIK_SECRET_KEY - Serve Authentik behind HTTPS only (NPM + valid certificate)
- Enable HSTS in NPM
- Restrict VM access — only NPM and trusted internal hosts should reach port 9000
- Back up
.envand the database regularly - Pin
AUTHENTIK_TAGin.envand update intentionally — don't uselatest
- Applications — configure SAML or OIDC apps for SSO
- Users & Groups — build your user directory
- Flows — customize authentication, enrollment, and recovery flows
- Sources — connect LDAP, Google, GitHub, or other OAuth/SAML sources
- Outposts — deploy the forward auth proxy or LDAP outpost for non-SAML apps
- AWS Identity Center — set up SAML federation with the correct
CSRF_TRUSTED_ORIGINSregion - Test email — send a test from Admin Interface → System → Email