Deploy Directus CMS on Kubernetes with PostgreSQL: Production-Ready Template

Running Directus in production requires coordinating a stateful database, persistent file storage, and network isolation. This template deploys Directus 11 backed by PostgreSQL 16 on Kubernetes, producing a namespace-isolated setup with ingress routing, resource quotas, and pod-level network policies.
| Component | Type | Port | Role |
|---|---|---|---|
| directus | Deployment | 8055 | Runs the Directus CMS application |
| directus-postgres | StatefulSet | 5432 | Runs PostgreSQL 16 as the primary database |
| directus-postgres-headless | Service (Headless) | 5432 | Stable DNS for the StatefulSet |
| directus-service | Service (ClusterIP) | 8055 | Exposes Directus internally |
| directus-ingress | Ingress | 8055 | Routes external HTTP traffic to Directus |
| directus-config | ConfigMap | - | Non-sensitive Directus environment variables |
| postgres-config | ConfigMap | - | Non-sensitive PostgreSQL environment variables |
| directus-secret | Secret | - | DB password, admin credentials, cookie secret |
| postgres-secret | Secret | - | PostgreSQL superuser password |
| directus-uploads-pvc | PVC | - | Persists uploaded files across pod restarts |
| pg-storage | PVC | - | Persists PostgreSQL data |
| directus-quota | ResourceQuota | - | Namespace-level CPU and memory ceilings |
| directus-limits | LimitRange | - | Default resource requests per container |
| database-policy | NetworkPolicy | - | Restricts DB ingress to Directus pods only |
| engine-ingress-policy | NetworkPolicy | - | Restricts Directus ingress to port 8055 |
Directus connects to PostgreSQL through the headless service DNS (directus-postgres-headless). The nginx Ingress routes traffic on directus.local to the ClusterIP service on port 8055. NetworkPolicies enforce isolation: PostgreSQL only accepts connections from app: directus pods, and Directus only accepts inbound traffic on port 8055. File uploads are decoupled from the application pod via a dedicated PVC.
hostpath StorageClass available (default on Docker Desktop and Minikube)directus.local added to /etc/hosts pointing to 127.0.0.1DB_PASSWORD and POSTGRES_PASSWORD to the same strong password, set SECRET to a random 32-character string, and update ADMIN_EMAIL and ADMIN_PASSWORD.DB_HOST is directus-postgres-headless and DB_DATABASE matches POSTGRES_DB across both ConfigMaps.ResourceQuota and LimitRange values to match your cluster capacity.kubectl get pods -n directus and confirm both pods show Running with all containers ready.http://directus.local and sign in with the admin credentials from your Secret.curl http://directus.local/server/ping and confirm it returns pong.This template configures a namespace-isolated Directus CMS deployment with a StatefulSet-backed PostgreSQL database, persistent storage for data and uploads, ingress routing, resource governance, and network-level access control.