x-info: github: https://github.com/goauthentik/authentik docs: https://goauthentik.io/docs changelog: https://github.com/goauthentik/authentik/releases homelab_status: stable last_updated: 2026-03-15 # Managed by Ansible — manual edits will be overwritten on next deploy. # Source: ansible/templates/stacks/authentik.stack.yml # Deploy: ansible-playbook -i inventory/hosts.ini playbooks/docker/deploy_authentik.yml # # DATA SAFETY NOTE: # This stack uses absolute bind mounts under /mnt/homelab/apps/authentik. # Deploy playbook preflight checks require these paths to exist before deploy, # which protects pre-existing Authentik data from accidental fresh bootstraps. version: "3.9" services: authentik-postgres: image: docker.io/library/postgres:16-alpine environment: - TZ=America/New_York - POSTGRES_DB={{ authentik_postgres_db | default('authentik') }} - POSTGRES_PASSWORD={{ vault_authentik_postgres_password }} - POSTGRES_USER={{ authentik_postgres_user | default('authentik') }} healthcheck: test: ["CMD-SHELL", "pg_isready -d $$POSTGRES_DB -U $$POSTGRES_USER"] interval: 30s timeout: 5s retries: 5 start_period: 20s volumes: - /mnt/homelab/apps/authentik/data/database:/var/lib/postgresql/data networks: - proxy-net deploy: replicas: 1 placement: constraints: - node.hostname == {{ authentik_placement_node | default('swarm-manager-1') }} resources: limits: memory: 1G cpus: "0.75" restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 60s update_config: parallelism: 1 order: stop-first failure_action: rollback delay: 10s monitor: 30s rollback_config: parallelism: 1 order: stop-first authentik-redis: image: redis:7-alpine command: ["--save", "60", "1", "--loglevel", "warning"] healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 volumes: - /mnt/homelab/apps/authentik/data/redis:/data networks: - proxy-net deploy: replicas: 1 placement: constraints: - node.hostname == {{ authentik_placement_node | default('swarm-manager-1') }} resources: limits: memory: 512M cpus: "0.50" restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 60s update_config: parallelism: 1 order: start-first failure_action: rollback delay: 10s monitor: 30s rollback_config: parallelism: 1 order: stop-first authentik-server: image: ghcr.io/goauthentik/server:{{ authentik_version | default('2025.10.1') }} command: ["server"] environment: - TZ=America/New_York - AUTHENTIK_POSTGRESQL__HOST=authentik-postgres - AUTHENTIK_POSTGRESQL__NAME={{ authentik_postgres_db | default('authentik') }} - AUTHENTIK_POSTGRESQL__PASSWORD={{ vault_authentik_postgres_password }} - AUTHENTIK_POSTGRESQL__USER={{ authentik_postgres_user | default('authentik') }} - AUTHENTIK_SECRET_KEY={{ vault_authentik_secret_key }} - AUTHENTIK_REDIS__HOST=authentik-redis ports: - "9000:9000" volumes: - /mnt/homelab/apps/authentik/data/media:/media - /mnt/homelab/apps/authentik/data/config:/config - /mnt/homelab/apps/authentik/data/blueprints:/blueprints/custom:ro networks: - proxy-net labels: - "homepage.name=Authentik" - "homepage.icon=si:authentik" - "homepage.url=https://sso.castaldifamily.com" - "homepage.description=Identity provider" deploy: labels: - "traefik.enable=true" - "traefik.http.routers.authentik.rule=Host(`sso.castaldifamily.com`)" - "traefik.http.routers.authentik.entrypoints=websecure" - "traefik.http.routers.authentik.tls=true" - "traefik.http.routers.authentik.tls.certresolver=cloudflare" - "traefik.http.routers.authentik.middlewares=security-headers@file,ratelimit-basic@file" - "traefik.http.services.authentik.loadbalancer.server.url=http://{{ edge_routing.swarm.bind_ip }}:9000" replicas: 1 placement: constraints: - node.hostname == {{ authentik_placement_node | default('swarm-manager-1') }} resources: limits: memory: 2G cpus: "1.0" restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 60s update_config: parallelism: 1 order: start-first failure_action: rollback delay: 10s monitor: 30s rollback_config: parallelism: 1 order: stop-first authentik-worker: image: ghcr.io/goauthentik/server:{{ authentik_version | default('2025.10.1') }} command: ["worker"] environment: - TZ=America/New_York - AUTHENTIK_POSTGRESQL__HOST=authentik-postgres - AUTHENTIK_POSTGRESQL__NAME={{ authentik_postgres_db | default('authentik') }} - AUTHENTIK_POSTGRESQL__PASSWORD={{ vault_authentik_postgres_password }} - AUTHENTIK_POSTGRESQL__USER={{ authentik_postgres_user | default('authentik') }} - AUTHENTIK_SECRET_KEY={{ vault_authentik_secret_key }} - AUTHENTIK_REDIS__HOST=authentik-redis volumes: - /mnt/homelab/apps/authentik/data/media:/media - /mnt/homelab/apps/authentik/data/config:/config networks: - proxy-net deploy: replicas: 1 placement: constraints: - node.hostname == {{ authentik_placement_node | default('swarm-manager-1') }} resources: limits: memory: 1G cpus: "0.75" restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 60s update_config: parallelism: 1 order: start-first failure_action: rollback delay: 10s monitor: 30s rollback_config: parallelism: 1 order: stop-first networks: proxy-net: external: true name: proxy-net