Authentik Common — Shared Application Configuration
Authentik_Common is the shared application layer for authentik —
the open-source identity provider (SSO via OIDC/SAML, LDAP, SCIM, MFA, and proxy
authentication; a self-hosted alternative to Okta, Auth0, and Keycloak). It is not
deployed on its own; instead it supplies the authentik-specific configuration that
both Authentik_GKE and Authentik_CloudRun
build on, so the two platform variants behave identically where it matters. End users
never configure this layer directly — it has no deployment UI inputs of its own — but
understanding what it provides explains the defaults you see in the platform docs.
For the infrastructure that actually provisions and runs authentik, see the platform guides (Authentik_GKE, Authentik_CloudRun) and the foundation guides (App_GKE, App_CloudRun, App_Common).
1. What this layer provides
| Area | Provided by Authentik_Common | Where it surfaces |
|---|---|---|
| Cryptographic secrets | Generates a stable AUTHENTIK_SECRET_KEY (64 chars) and the akadmin bootstrap password (24 chars) and stores both in Secret Manager | Injected automatically; retrieve via Secret Manager (see below) |
| Container image | Thin custom build FROM ghcr.io/goauthentik/server with a cloud entrypoint; built via Cloud Build. application_version = "latest" is pinned to a known-good release (authentik publishes no latest tag) | container_image output of the platform deployment |
| Database engine | Fixes Cloud SQL for PostgreSQL 15 as the only supported engine (authentik requires PostgreSQL ≥ 14) | §Database in the platform guides |
| Database bootstrap | Defines the single first-deploy job (db-init) that creates the role and database and grants cloudsqlsuperuser defensively | initialization_jobs output |
| No Redis | authentik ≥ 2025.10 keeps cache, sessions, task queue, and the WebSocket channel layer in PostgreSQL — no cache service is provisioned | §Overview in the platform guides |
| Media storage | Declares a GCS bucket mounted at /media via GCS Fuse for uploaded icons and flow backgrounds | storage_buckets output |
| Worker co-location | The entrypoint launches ak worker in the background alongside the server in the same container, on dedicated loopback listen ports so the server owns :9000 | Application behaviour in the platform guides |
| Health checks | Default startup probe GET /-/health/ready/ (generous first-boot threshold) and liveness probe GET /-/health/live/ — both unauthenticated | §Observability in the platform guides |
2. Secrets in Secret Manager
Two secrets are generated automatically and stored in Secret Manager under
secret-<tenant-prefix>-<application-name>-*:
AUTHENTIK_SECRET_KEY(...-secret-key) — the DjangoSECRET_KEYequivalent. authentik uses it to sign sessions and cookies and derives internal encryption from it. It is generated once (64 random characters) and must remain stable for the deployment's life — rotating it invalidates every active session and makes encrypted fields (stored credentials, tokens) unreadable.AUTHENTIK_BOOTSTRAP_PASSWORD(...-bootstrap-password) — the initial password for the built-inakadminadmin user. authentik applies it on the first start only (together withAUTHENTIK_BOOTSTRAP_EMAIL, defaultadmin@techequity.cloud); later password changes happen in the application. Supplying an explicitbootstrap_passwordinput overrides the auto-generated value.
Retrieve the secrets after deployment:
# List secrets for this deployment (names include the tenant prefix):
gcloud secrets list --project "$PROJECT" --filter="name~authentik"
# Read the bootstrap password (first login as akadmin):
gcloud secrets versions access latest \
--secret=<secret-...-bootstrap-password> --project "$PROJECT"
# Read the secret key (do NOT rotate it):
gcloud secrets versions access latest \
--secret=<secret-...-secret-key> --project "$PROJECT"
The database password is generated and managed separately by the foundation; its
secret name is reported in the platform deployment outputs
(database_password_secret). See App_Common for the shared secret
and Workload Identity model.
3. Thin custom image and entrypoint mapping
The image is a minimal wrapper over the official authentik server image — no application code is modified:
- App-specific
AUTHENTIK_VERSIONbuild ARG. The foundation injectsAPP_VERSIONintobuild_argsand wins the merge, so the Dockerfile derives itsFROMtag from the app-specificAUTHENTIK_VERSIONARG instead. authentik publishes only version tags on GHCR (nolatest), soapplication_version = "latest"is pinned to a known-good release (2026.5.4) at build time. cloud-entrypoint.shmapsDB_*→AUTHENTIK_POSTGRESQL__*at runtime. The platform injects standardDB_HOST,DB_PORT,DB_NAME,DB_USER,DB_PASSWORDvariables; the entrypoint aliases them onto authentik'sAUTHENTIK_POSTGRESQL__HOST/PORT/NAME/USER/PASSWORDconvention. This happens in the entrypoint (not declaratively) for two platform reasons: Cloud Run does not interpolate$(VAR)env references, and a synced-secret key namedAUTHENTIK_POSTGRESQL__PASSWORDwould be rejected by the GKE SecretSync CRD (__violates itstargetKeyregex). Values already set explicitly are never overridden.- SSL mode by connection type. When the DB host is a Unix-socket directory (the
Cloud SQL Auth Proxy on Cloud Run) or loopback (
127.0.0.1/localhost— the Auth Proxy sidecar on GKE),AUTHENTIK_POSTGRESQL__SSLMODEdefaults todisable: the proxy serves both forms, is TLS-terminated, and does not speak SSL itself — requiring SSL on127.0.0.1fails with "server does not support SSL, but SSL was required". Only direct TCP to any other host defaults torequire(direct private-IP connections to Cloud SQL reject unencrypted traffic). - Co-located worker. In docker-compose authentik runs
ak workeras a second container. On Cloud Run / single-pod GKE the entrypoint starts it in the background beforeexec-ing the server (the same pattern as Chatwoot's co-located Sidekiq worker). Both processes shareAUTHENTIK_SECRET_KEYand the Postgres-backed task queue. The worker is started with dedicated loopback listen ports (AUTHENTIK_LISTEN__HTTP=127.0.0.1:9001,AUTHENTIK_LISTEN__HTTPS=127.0.0.1:9444,AUTHENTIK_LISTEN__METRICS=127.0.0.1:9301): the worker binary also starts an HTTP listener and inherits the server's default0.0.0.0:9000, so co-located in one container it can win the bind race and answer every route — the health endpoints included — with empty 200s (a blank UI with phantom-healthy probes). Pinning the worker to loopback ports guarantees the server owns:9000. This is why the Cloud Run variant defaults tocpu_always_allocated = trueandmin_instance_count = 1— the worker must keep running between requests. - No migration step in the entrypoint — authentik's server runs its own advisory-lock-guarded migrations on every startup (see below).
Baseline environment set by this layer (overridable via environment_variables):
AUTHENTIK_BOOTSTRAP_EMAIL (default admin@techequity.cloud),
AUTHENTIK_ERROR_REPORTING__ENABLED = "false",
AUTHENTIK_DISABLE_UPDATE_CHECK = "true", and AUTHENTIK_LOG_LEVEL = "info".
The container listens on port 9000.
Note that entrypoint and Dockerfile edits are baked into the custom image and require
a rebuild; the db-init script is mounted at apply time and changes take effect on
the next apply without a rebuild.
4. Database engine and bootstrap
authentik requires PostgreSQL 15 (≥ 14); the engine is fixed and MySQL is not
supported. On the first deployment a single one-shot job (db-init) runs using
postgres:15-alpine and idempotently:
- Waits for PostgreSQL to be reachable (Auth Proxy socket directory on Cloud Run, proxy TCP on GKE),
- Creates (or updates) the tenant-scoped application role with the generated password,
- Creates the application database if missing — owned by
postgres, because Cloud SQL'spostgreslogin cannotSET ROLEto application roles — and grants full privileges on the database and thepublicschema, - Grants
cloudsqlsuperuserto the application role defensively, so any futureCREATE EXTENSION IF NOT EXISTSin upstream migrations is a no-op instead of a "must be superuser" failure, - Signals the Cloud SQL Auth Proxy sidecar to shut down so the job completes.
There is no separate schema or migrate job: authentik's server applies its own Django migrations on every startup, guarded by a PostgreSQL advisory lock so concurrent instances don't collide. Version upgrades therefore need no extra migration step — the first instance of the new revision migrates the schema while the startup probe's generous threshold keeps the rollout waiting.
Inspect the database directly with:
gcloud sql connect <instance-name> --user=<db-user> --database=<db-name> --project "$PROJECT"
The instance, database, and user names are in the platform deployment outputs (note the database and user names are tenant-prefixed).
5. GCS media volume
authentik stores uploaded media — application icons and flow backgrounds — under
/media. This layer declares a dedicated Cloud Storage bucket
(name_suffix = "storage") and mounts it at /media via GCS Fuse with
uid=1000,gid=1000 (matching the upstream authentik runtime user). Media is plain
files with no locking requirements, so GCSFuse is safe, and uploads survive instance
replacement and scaling events on both platforms.
The bucket name follows the foundation formula
gcs-<application_name><tenant-prefix>-storage (app-scoped). List it with:
gcloud storage buckets list --project "$PROJECT"
gcloud storage ls gs://gcs-<service-name>-storage/
6. Health probe behaviour
Both authentik health endpoints are unauthenticated, which is a hard requirement for platform probes (Cloud Run's front end and the GKE kubelet probe without credentials):
- Startup:
GET /-/health/ready/returns 200 once migrations have completed and the database is reachable. The first boot runs authentik's full migration suite, so the default threshold is generous — 60 s initial delay plus 40 × 15 s retries (roughly 11 minutes) before the rollout is failed. - Liveness:
GET /-/health/live/is a lightweight process-alive check (60 s delay, 3 × 30 s).
Do not repoint the probes at authenticated pages — an endpoint that returns 401/403 to the unauthenticated prober keeps the revision/pod permanently unready even though the application booted fine.
For the authentik-specific, user-facing configuration (variables by group, outputs, and how to explore each service from the Console and CLI), see the platform guides: Authentik_GKE and Authentik_CloudRun.