# Authentik (SSO / Identity Provider)

## Overview

Authentik is the identity provider and single sign-on (SSO) gateway for all
externally-accessible services on Centerpoint. It implements ForwardAuth middleware
for Traefik, meaning that any request arriving at an external route tagged with
`authentik-auth@docker` is intercepted and validated by Authentik before being
forwarded to the backend service.

Authentik also serves as an OAuth2/OIDC provider — services like BookStack use
OIDC for native user login rather than ForwardAuth.

## Access

| Type      | URL                                       | Notes                                  |
|-----------|-------------------------------------------|----------------------------------------|
| Internal  | `https://auth.home.local`                 | LAN access via Step-CA TLS             |
| External  | `https://auth.jeevesconsults.ca`          | Internet-facing — OIDC redirect target |

The external URL (`auth.jeevesconsults.ca`) is the one registered as the OIDC issuer
with downstream services. It must be reachable by browsers completing OAuth2 flows.

## Containers in This Stack

| Container               | Image                                    | Role                                  |
|-------------------------|------------------------------------------|---------------------------------------|
| `authentik-server`      | `ghcr.io/goauthentik/server:2026.5.x`   | HTTP server + ForwardAuth endpoint    |
| `authentik-worker`      | `ghcr.io/goauthentik/server:2026.5.x`   | Background task worker (Rust entry)   |
| `authentik-postgresql`  | `postgres:16-alpine`                     | Primary database                      |
| `authentik-geoip`       | `ghcr.io/maxmind/geoipupdate:v7.x`      | GeoIP database updater (MaxMind)      |

### Startup Order

`authentik-postgresql` must reach a healthy state before `authentik-server` and
`authentik-worker` start. The `authentik-geoip` sidecar runs independently.

## Configuration

**Compose project:** `authentik`

### Key Environment Variables

| Variable                       | Value / Notes                                              |
|--------------------------------|------------------------------------------------------------|
| `AUTHENTIK_SECRET_KEY`         | **REDACTED** — long random string, must stay constant      |
| `AUTHENTIK_POSTGRESQL__HOST`   | `authentik-postgresql`                                     |
| `AUTHENTIK_POSTGRESQL__NAME`   | `authentik`                                                |
| `AUTHENTIK_POSTGRESQL__USER`   | `authentik`                                                |
| `AUTHENTIK_POSTGRESQL__PASSWORD` | **REDACTED**                                             |
| `AUTHENTIK_REDIS__HOST`        | `redis` (internal sidecar or external Redis)               |
| `AUTHENTIK_LISTEN__HTTP`       | `0.0.0.0:9000` — explicit bind required for Docker bridge  |
| `AUTHENTIK_ERROR_REPORTING__ENABLED` | `false`                                            |

> **Important:** `AUTHENTIK_LISTEN__HTTP: "0.0.0.0:9000"` is required in Authentik
> 2026.5+. Newer versions default to `[::]` (IPv6 wildcard) which Docker bridge
> networks cannot reach via IPv4. Without this override, ForwardAuth requests from
> Traefik fail silently.

### ForwardAuth Middleware

The Authentik ForwardAuth middleware is defined on the `authentik-server` container
labels and is available to all services on `traefik-net` as:

```
authentik-auth@docker
```

Example usage on a protected external route:

```yaml
labels:
  - "traefik.http.routers.<name>-ext.middlewares=authentik-auth@docker,plex-geoblock@file,crowdsec-bouncer@file"
```

### OIDC Configuration (for native OIDC apps)

Applications using OIDC (e.g. BookStack) configure Authentik as their provider
with the following settings:

| Setting               | Value                                                           |
|-----------------------|-----------------------------------------------------------------|
| Issuer URL            | `https://auth.jeevesconsults.ca/application/o/<app-slug>/`     |
| JWKS URL              | `<issuer>/.well-known/jwks.json`                               |
| Client ID             | Per-application (set in Authentik admin UI)                    |
| Client Secret         | **REDACTED** — set per-application                              |
| `email_verified`      | Requires custom Scope Mapping returning `true` (2026.5+ change) |

## Volumes / Bind Mounts

| Host Path / Volume                  | Container Path    | Purpose                                 |
|-------------------------------------|-------------------|-----------------------------------------|
| `authentik_media`                   | `/media`          | Uploaded assets (logos, avatars)        |
| `authentik_custom-templates`        | `/templates`      | Custom email / flow templates           |
| `authentik_postgresql_data`         | `/var/lib/postgresql/data` | PostgreSQL data directory      |
| `authentik_geoip_data`              | `/usr/share/GeoIP` | MaxMind GeoIP databases                |

All volumes are named Docker volumes managed by Portainer.

### Sub-section: PostgreSQL

The `authentik-postgresql` container is a dedicated Postgres 16 sidecar that stores
all Authentik state: users, groups, policies, flows, tokens, and audit logs. It is not
shared with any other service.

Database credentials are passed to the server via `AUTHENTIK_POSTGRESQL__*` environment
variables. The container is on the `authentik-internal` network only — it is never
exposed to `traefik-net` or the host.

### Sub-section: GeoIP Updater

`authentik-geoip` runs the MaxMind GeoIPUpdate daemon, which downloads and refreshes
the `GeoLite2-City` and `GeoLite2-ASN` databases on a schedule. The databases are
shared into `authentik-server` via the `authentik_geoip_data` volume.

A MaxMind account and licence key (**REDACTED**) are required for the GeoIP databases.

### Sub-section: Worker

`authentik-worker` runs as the same container image as `authentik-server` but with
the worker entrypoint. It handles background tasks: email delivery, outpost health
checks, blueprint application, and event cleanup. Since Authentik 2025.10+, the
worker uses a Rust-based entrypoint for improved performance.

## Dependencies

- `authentik-postgresql` (must be healthy before server/worker start)
- `traefik-net` (server must be on this network for ForwardAuth to reach it)
- MaxMind account for GeoIP updates (not strictly required, but GeoIP features
  will be unavailable without it)

## Notes / Gotchas

- If the `AUTHENTIK_SECRET_KEY` changes, all tokens, sessions, and cookies are
  immediately invalidated — all users will be logged out across all services.
- Authentik's admin interface is at `/if/admin/`. Initial admin credentials are
  set via the `AUTHENTIK_BOOTSTRAP_PASSWORD` env var on first start.
- For OIDC apps: `email_verified` defaults to `false` since Authentik 2025.10. Create
  a custom Scope Mapping that hard-codes `"email_verified": True` and attach it to the
  OAuth2 provider.
- Existing local users who also log in via OIDC must have their **External Auth ID**
  set in Admin → Users → Edit → External Auth ID to match the `sub` claim from the
  OIDC token, otherwise two separate accounts will be created.
- `DOZZLE_ENABLE_SHELL=true` on Dozzle requires that this admin account is separate
  from the Authentik service account.

---
*Last Updated: 2026-06-16*