Files
HiveGrid-Wireframes/hivegrid-cloud/infra/authentik

infra/authentik — Self-Hosted Authentik IdP Stack

This directory contains the artifacts to deploy a self-hosted Authentik identity-provider instance on the staging Hetzner host (boilerplate-staging, see docs/improvement-plan/archive/STAGING-ACCESS.md) via the existing Coolify-managed Docker-Compose runtime.

Purpose

  • Centralise admin authentication behind an external IdP (Phase 09 #82) instead of trusting the application's own user table
  • Enforce MFA-TOTP for super-admins at the IdP layer (group-policy)
  • Provide a group-based access model (toolctrl-admin, toolctrl-staff, toolctrl-users) that the admin panel + future tenant-SSO consume
  • Provide a federation target for the Backlog #66 customer-tenant-SSO (second OIDC provider definition is shipped as a disabled placeholder)
  • Aggregate auth-audit events (login / logout / mfa-enroll / group-change) so they can be ingested by the Phase 10 audit-log (#67)

The companion ultra-lite alternative (GLAuth, LDAP-only, ~50 MB RAM) is documented in docs/operations/authentik-alternatives.md and is not the default — it lacks OIDC, MFA-enforcement, brand-flows, and blueprints.

Prerequisites

  • Hetzner host with ≥ 2 GB RAM free for the Authentik stack (server: ~600 MB, worker: ~400 MB, postgres: ~300 MB, redis: ~150 MB, plus headroom). The staging host has 30 GiB RAM with plenty of headroom.
  • Docker Engine ≥ 24 + Docker Compose v2 (provided by Coolify)
  • Traefik v3.6 reverse-proxy from coolify-proxy (Let's Encrypt ACME via the letsencrypt cert-resolver)
  • DNS record auth.boiler.saas-ctrl.com → 46.225.5.93 (Cloudflare-managed; see docs/operations/authentik-setup.md for the cf-cli snippet that creates it)
  • Sentry self-hosted stack from Phase 02 #29 reachable at sentry.boiler.saas-ctrl.com (Authentik containers report their own errors to it via AUTHENTIK_SENTRY__DSN)

Layout

infra/authentik/
├── README.md                       # this file
├── .gitignore                      # excludes runtime volumes + secrets
├── UPSTREAM.md                     # pinned Authentik tag + image pin rationale
├── docker-compose.yml              # 4-service compose: server, worker, postgresql, redis
├── traefik.labels.yml              # canonical Traefik label-set for auth.<domain>
├── .env.example                    # template for AUTHENTIK_* secrets
├── bootstrap/
│   ├── bootstrap.sh                # waits for /-/health/ready/ then loads blueprints
│   └── blueprints/
│       ├── 01-groups.yaml          # toolctrl-admin / -staff / -users groups + attrs
│       ├── 02-policies.yaml        # password policy + MFA-enforce + brute-force
│       └── 03-application-toolctrl-admin.yaml  # OIDC provider for admin panel
├── backup/                         # daily backup container
│   ├── Dockerfile
│   ├── backup.sh
│   └── crontab
└── scripts/
    └── smoke.sh                    # post-deploy smoke checks (curl-only)

Deploy

See docs/operations/authentik-setup.md for the full Coolify-deploy + DNS + backup + restore runbook. Deployment is operator-owned — this directory ships the artifacts; the operator runs the Coolify side.

High-level:

  1. Operator creates the Coolify "Docker Compose" service against this repo pointing at infra/authentik/docker-compose.yml.
  2. Operator copies .env.example → Coolify-Vault and fills in secrets (AUTHENTIK_SECRET_KEY from openssl rand -base64 60, etc.).
  3. Coolify deploy boots postgres, redis, then server + worker.
  4. Operator runs bootstrap/bootstrap.sh once against the running stack to apply blueprints (groups + policies + admin-panel OIDC provider).
  5. Operator runs scripts/smoke.sh to verify TLS, health, OIDC discovery.

Versioning

  • Authentik pin: ghcr.io/goauthentik/server:2026.2.3 and ghcr.io/goauthentik/proxy:2026.2.3 (see UPSTREAM.md for rationale).
  • Postgres pin: postgres:16-alpine.
  • Redis pin: redis:7-alpine.

Scope

  • Authentik server + worker + dedicated postgresql + dedicated redis — these databases MUST NOT be shared with the boilerplate application's own Postgres/Redis (separate compromise blast-radius + separate backup/restore cycle).
  • No Outposts — pure OIDC use-case; the reverse-proxy outpost concept is intentionally out of scope for this phase.
  • No public self-registration — admin-only invitation flow.