Files
dezky/infrastructure/production/fleet/authentik
Ronni Baslund 99cd86cd3a
ci / typecheck (map[dir:apps/booking name:booking]) (push) Failing after 7s
ci / test (push) Failing after 7s
ci / typecheck (map[dir:services/platform-api name:platform-api]) (push) Failing after 6s
ci / typecheck (map[dir:apps/portal name:portal]) (push) Has been cancelled
ci / typecheck (map[dir:apps/website name:website]) (push) Has been cancelled
feat(infra): full dezky branding on Authentik (logo, carbon bg, flow title)
branding_logo / branding_default_flow_background are file-path fields (reject
data URIs), so the dezky logo + carbon background are injected via the brand's
custom CSS (data URIs allowed there): logo replaces the authentik wordmark,
background overrides the forest. Auth-flow title -> "Welcome to Dezky".
Signal-green primary button retained.
2026-06-08 19:54:44 +02:00
..

fleet/authentik — identity provider (auth.dezky.eu)

Authentik, mirroring the dev docker-compose service but pointed at the in-cluster data tier. Deployed via the k3s Helm controller (helmchart.yaml, which mirrors values.yaml). Live at https://auth.dezky.eu (Let's Encrypt).

  • External Postgres (postgres.dezky-data, db/user authentik) + Redis (redis.dezky-data) — chart's bundled subcharts disabled.
  • Secrets via global.envFrom → the authentik-secret Secret (generated on-box; see secret.example.yaml). DB/Redis passwords match the dezky-data secrets.
  • Ingress: Traefik + cert-manager letsencrypt-prod.
  • error_reporting off, update-check off, bootstrap email admin@dezky.eu.

Deploy

# 1. secret (reads DB/Redis pw from dezky-data so they match; rest generated)
ADB=$(kubectl -n dezky-data get secret postgres-secret -o jsonpath='{.data.AUTHENTIK_DB_PASSWORD}' | base64 -d)
RDB=$(kubectl -n dezky-data get secret redis-secret    -o jsonpath='{.data.REDIS_PASSWORD}'        | base64 -d)
kubectl create namespace dezky-auth --dry-run=client -o yaml | kubectl apply -f -
kubectl -n dezky-auth create secret generic authentik-secret \
  --from-literal=AUTHENTIK_SECRET_KEY=$(openssl rand -hex 50) \
  --from-literal=AUTHENTIK_POSTGRESQL__PASSWORD="$ADB" \
  --from-literal=AUTHENTIK_REDIS__PASSWORD="$RDB" \
  --from-literal=AUTHENTIK_BOOTSTRAP_PASSWORD=$(openssl rand -hex 16) \
  --from-literal=AUTHENTIK_BOOTSTRAP_TOKEN=$(openssl rand -hex 32)
# 2. install
kubectl apply -f helmchart.yaml
kubectl -n dezky-auth rollout status deploy/authentik-server --timeout=300s

First login

# akadmin password (store in Bitwarden):
kubectl -n dezky-auth get secret authentik-secret -o jsonpath='{.data.AUTHENTIK_BOOTSTRAP_PASSWORD}' | base64 -d; echo

Log in at https://auth.dezky.eu as akadmin / that password.

Blueprints + branding (APPLIED)

blueprints/ holds prod blueprints (applied & successful on node1):

  • brand.yaml — dezky branding on the default brand (title + signal-green custom CSS). This is what puts the login page in dezky colors.
  • portal-application.yamldezky-portal OIDC app/provider (https://app.dezky.eu/api/auth/callback).
  • operator-application.yamldezky-operator OIDC app/provider (https://operator.dezky.eu/auth/oidc/callback) + dezky-platform-admins group + an access policy restricting operator login to that group.

Client secrets live in authentik-secret (PORTAL_OIDC_CLIENT_SECRET, OPERATOR_OIDC_CLIENT_SECRET) — the apps must reuse the SAME values.

Applying them (two gotchas, both handled)

  1. invalidation_flow is REQUIRED on OAuth2 providers in Authentik 2026.5 (dev's 2025.10 didn't need it) — both providers set it via !Find.
  2. ConfigMap mounts present files as symlinks, which Authentik's discovery won't read. So the worker uses an initContainer that copies the ConfigMap into an emptyDir as real files at /blueprints/custom:
    kubectl -n dezky-auth create configmap authentik-blueprints \
      --from-file=blueprints/ --dry-run=client -o yaml | kubectl apply -f -
    # patch worker: add bp-src(configMap) + bp-cust(emptyDir) + initContainer
    #   `cp -L /bp-src/*.yaml /bp-cust/`, mount bp-cust at /blueprints/custom
    kubectl -n dezky-auth rollout restart deploy/authentik-worker
    # apply each (or let discovery): ak apply_blueprint custom/<file>.yaml
    

    The chart's worker.volumes value did NOT take effect on this chart version, hence the direct Deployment patch. Caveat: a helm upgrade of Authentik reverts the patch — re-apply it (move it into a custom image or a post-render kustomize patch to make it durable). TODO.

Still deferred

  • Rebrand of the "Powered by authentik" string (web-bundle sed, needs a root lifecycle override) — cosmetic; the colors are done via the brand CSS.
  • Pin the chart version (currently latest → app 2026.5.2).