Learn Authentik - Kubernetes Deployment
Episode 24 of 31

Learn Authentik - Kubernetes Deployment

Deploying Authentik on Kubernetes with the official Helm chart: separating server and worker, provisioning PostgreSQL and Redis, configuring via ConfigMap and Secret, and setting up ingress and outposts inside the cluster.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Introduction

In episode 23, we built a high availability architecture: several Authentik instances behind a load balancer, a replicated database, and Redis serving as cache and message queue. The question that immediately follows is: how do you manage all those instances consistently, perform rolling updates without downtime, and enforce the same configuration on every node?

The answer brings you to this episode's topic: Kubernetes. If Docker Compose is like managing a single house — all the furniture arranged in the same compose file — then Kubernetes is like the property manager for an apartment complex: it handles scheduling residents into available units, ensures broken units are promptly replaced, and keeps the same rules across the whole complex. This episode guides you through deploying Authentik on a cluster, understanding each component's role, and setting up outposts that live inside the cluster.

Why Kubernetes Is the Next Step

Authentik essentially consists of two workloads that work together:

  • Server — serves all HTTP traffic: the admin UI, login pages, flow executor, OAuth2/OIDC/SAML endpoints, and the API.
  • Worker — handles background tasks: email delivery, event processing, blueprint synchronization, and outpost management.

Besides those, Authentik depends on PostgreSQL for all persistent data and Redis as the task queue broker and cache. In Kubernetes, all four become declaratively managed objects: you write what you want it to be, and the control plane drives toward that state. The server and worker become Deployments, the database and cache are best as StatefulSets, and external access enters through an Ingress.

The benefits you get: self-healing (dead pods are replaced automatically), horizontal scaling with HPA, rolling updates with new image versions, and configuration that can be reviewed like code. This is why the manually built HA from episode 23 can be delegated to a platform.

Official Helm Chart: The Easiest Path

The Authentik team maintains the official Helm chart in the goauthentik/authentik repository. The chart already provides server and worker Deployments, services, built-in health probes, ingress options, plus the Bitnami PostgreSQL and Redis subcharts.

helm repo add authentik https://charts.goauthentik.io
helm repo update

The chart uses values from values.yaml to render all Kubernetes objects. Here's a minimal example taken from the official documentation:

Minimal values.yaml
authentik:
  secret_key: "GantiDenganSecretAcakPanjangMinimal50Karakter"
  postgresql:
    password: "GantiDenganPasswordDatabase"
server:
  ingress:
    enabled: true
    ingressClassName: nginx
    hosts:
      - auth.example.com
postgresql:
  enabled: true
  auth:
    password: "GantiDenganPasswordDatabase"
redis:
  enabled: true

On first installation, the chart automatically applies the database schema migrations. You can confirm all components are running with kubectl get pods -n authentik.

Secrets and ConfigMaps: Separating What's Sensitive

The Helm chart renders values.yaml values into two object types: ConfigMap for non-sensitive values (database host, database name, log level) and Secret for secret values (database keys, AUTHENTIK_SECRET_KEY). These variables are the source of configuration for the server and worker — from AUTHENTIK_POSTGRESQL__HOST, AUTHENTIK_REDIS__HOST, to AUTHENTIK_SECRET_KEY.

The golden rule: never put secret values directly in a values.yaml committed to Git. Use mechanisms like Helm --set at deploy time, existingSecret referencing a separately created Secret, or integration with an external secret operator (for example for HashiCorp Vault, as covered in the secret management series). That way, rotating a key only means replacing one Secret without re-rendering the whole chart.

Use existingSecret for the secret_key
authentik:
  existingSecret: authentik-secret

That Secret only needs to contain a key named authentik_secret_key. Its value must be identical on all server and worker instances — if one pod uses a different key, sessions and tokens issued there can't be verified by other pods.

PostgreSQL and Redis: Bundled vs External

The PostgreSQL and Redis subcharts, enabled via postgresql.enabled and redis.enabled, are very helpful for experimentation. However, the official documentation states clearly that the chart's built-in database is intended for demonstration and testing environments.

Warning

For production, use separately managed PostgreSQL — for example the CloudNativePG operator, the Zalando Postgres Operator, or a managed database from a cloud provider. This matters because: (1) database data is more resilient to loss than a single-node PV, (2) point-in-time backups are easier, and (3) recovery doesn't depend on the Kubernetes cluster itself.

If using an external database, simply set postgresql.enabled: false and point authentik.postgresql.host at the external address. Data is stored in a StatefulSet with a PersistentVolumeClaim — make sure the storageClass fits your I/O needs and consider periodic snapshots at the storage level.

Ingress and TLS

The only external entry point is the Ingress pointing to the server Service. This is the right place to terminate TLS. With cert-manager, Let's Encrypt certificates can be renewed automatically:

Ingress with cert-manager
server:
  ingress:
    enabled: true
    ingressClassName: nginx
    hosts:
      - auth.example.com
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-prod
    tls:
      - hosts:
          - auth.example.com
        secretName: authentik-tls

Don't leave AUTHENTIK_HOST and AUTHENTIK_REDIRECT__... on plain HTTP — the stored redirect URIs must match the scheme you choose exactly (episode 8). The issued certificates can be inspected via kubectl get certificates -n authentik.

Outposts Inside the Cluster

The proxy and LDAP outposts covered in episodes 11 and 18 can also run as Kubernetes objects. Here's how: create an outpost of type Kubernetes, then prepare a service connection containing the API URL and token. From there, Authentik deploys the outpost as its own Deployment + Service inside the cluster, complete with an auto-update mechanism when the outpost gets new settings.

KubernetesOutpost as a separate Deployment (condensed)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: authentik-outpost-proxy
  namespace: authentik
spec:
  replicas: 2
  selector:
    matchLabels:
      app: authentik
      component: outpost-proxy
  template:
    metadata:
      labels:
        app: authentik
        component: outpost-proxy
    spec:
      containers:
        - name: outpost
          image: ghcr.io/goauthentik/proxy:2025.10
          ports:
            - containerPort: 9000
          envFrom:
            - secretRef:
                name: authentik-outpost-token

An outpost inside the cluster has a big advantage: routes between applications run over stable internal cluster DNS, and the /outpost.goauthentik.io/ping health check can be used as a liveness probe. Make sure the service connection token is stored as a Secret, because a leaked token means anyone can control your outpost.

Understanding Manifests: Reading Behind the Chart

For learning purposes, it's also worth seeing the raw shape of what the chart generates. Render all templates with helm template authentik authentik/authentik -f values.yaml and look at the server Deployment. Inside you'll find the same patterns you learned in the Kubernetes series: the same Authentik image for both Deployments, args distinguishing the role (server vs worker), the /-/health/ready/ probe for readiness, and envFrom pulling values from ConfigMap and Secret.

From there, add the hallmarks of a production deployment: resources.requests and resources.limits for CPU and memory, a HorizontalPodAutoscaler that adds server replicas when CPU rises, and podAntiAffinity so server replicas don't pile up on the same node — so losing one node doesn't kill all of Authentik.

Closing

In this episode 24, you learned to deploy Authentik on Kubernetes via the official Helm chart: separating the server and worker roles, understanding how configuration values become ConfigMap and Secret, choosing between the chart's bundled PostgreSQL/Redis and external ones, configuring ingress with TLS, and placing outposts inside the cluster. You also learned that secret values must never go into Git, and that the chart's built-in health probes are the foundation of reliability on the platform.

Key takeaways:

  • The server and worker are two Deployments with the same image, differentiated by a role argument.
  • The chart's bundled PostgreSQL and Redis are for experimentation only; production uses separately managed ones.
  • AUTHENTIK_SECRET_KEY and database credentials must be consistent across all pods and stored as Secrets.
  • Ingress is the only entry point; TLS terminates here together with cert-manager.
  • Kubernetes outposts are managed via a service connection and a token that must be tightly guarded.

A healthy deployment still needs watchful eyes. In episode 25, we cover Monitoring & Performance: exposing Prometheus metrics on a dedicated port, monitoring key metrics like login success and failure rates plus latency, setting log levels, and configuring alerting so you know before users complain. See you in episode 25!

Learn Authentik - Kubernetes Deployment | Learning Authentik