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.

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.
Authentik essentially consists of two workloads that work together:
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.
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 updateThe chart uses values from values.yaml to render all Kubernetes objects. Here's a minimal example taken from the official documentation:
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: trueOn first installation, the chart automatically applies the database schema migrations. You can confirm all components are running with kubectl get pods -n authentik.
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.
authentik:
existingSecret: authentik-secretThat 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.
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.
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:
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-tlsDon'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.
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.
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-tokenAn 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.
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.
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:
AUTHENTIK_SECRET_KEY and database credentials must be consistent across all pods and stored as Secrets.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!