---
title: "Deploy on Managed Kubernetes"
url: "https://docs.caracal.run/operations/cloud-reference-deployments/"
markdown_url: "https://docs.caracal.run/markdown/operations/cloud-reference-deployments.md"
description: "Concrete managed-Kubernetes reference for Caracal with External Secrets, cert-manager TLS, and managed Postgres and Redis."
page_type: "workflow"
concepts: []
requires: []
---

# Deploy on Managed Kubernetes

Canonical URL: https://docs.caracal.run/operations/cloud-reference-deployments/
Markdown URL: https://docs.caracal.run/markdown/operations/cloud-reference-deployments.md
Description: Concrete managed-Kubernetes reference for Caracal with External Secrets, cert-manager TLS, and managed Postgres and Redis.
Page type: workflow
Concepts: none
Requires: none

---

This page turns the [Choose a Cloud Profile](/operations/cloud-native-profiles/) map into a concrete, copy-paste deployment. The chart is cloud-agnostic by design; the only per-cloud surface is the secret-store authentication, the storage class, and the ingress annotations.

The reference artifacts live in `infra/helm/caracal/examples`:

- `values.cloud-managed.yaml` — production overlay with externalized state, cert-manager TLS ingress, ServiceMonitor, and tightened egress.
- `external-secrets/` — External Secrets Operator stores for AWS, GCP, and Azure plus one cloud-agnostic `ExternalSecret`.

## Prerequisites

| Component | Why |
| --- | --- |
| Managed Postgres | Authoritative product, policy, audit, and delegation state. |
| Managed Redis | Streams for audit, revocation, policy invalidation, and coordination. |
| [External Secrets Operator](https://external-secrets.io/) | Provisions `caracal-runtime` from your secret manager so no plaintext secret is rendered. |
| [cert-manager](https://cert-manager.io/) | Issues TLS certificates for the Gateway and API ingress. |
| Prometheus Operator | Consumes the chart `ServiceMonitor` and `PrometheusRule`. |

## 1. Store Secret Material

Load the Caracal secret material into your secret manager under the keys the `ExternalSecret` reads:

| Secret manager key | Contents |
| --- | --- |
| `caracal/postgres` | `username`, `password`, `host`, `port`, `database`. |
| `caracal/redis` | `password`, `host`, `port`, `database`. |
| `caracal/zone-kek` | Zone key-encryption key. |
| `caracal/audit-hmac-key`, `caracal/streams-hmac-key`, `caracal/gateway-sts-hmac-key` | Integrity keys. |
| `caracal/admin-token`, `caracal/coordinator-token` | Control-plane tokens. |
| `caracal/sts-admin-token`, `caracal/audit-admin-token`, `caracal/metrics-bearer` | Optional service tokens. |

## 2. Apply the Secret Store and ExternalSecret

Pick the store for your cloud and apply it with the agnostic `ExternalSecret`:

```bash
cd infra/helm/caracal/examples
kubectl apply -f external-secrets/secretstore-aws.yaml
kubectl apply -f external-secrets/externalsecret-runtime.yaml
```

The `ExternalSecret` composes `databaseUrl` and `redisUrl` and materializes the exact keys the chart mounts, so `secrets.create` stays `false`.

## 3. Install the Chart with the Overlay

```bash
helm upgrade --install caracal infra/helm/caracal \
  --namespace caracal --create-namespace \
  -f infra/helm/caracal/examples/values.cloud-managed.yaml \
  --set secrets.database.host=<managed-postgres-host> \
  --set secrets.redis.host=<managed-redis-host>
```

Stable mode enforces externalized Postgres and Redis hosts and forbids in-chart plaintext secrets, so the render fails fast if either is left at a default.

## Per-Cloud Substitutions

| Setting | AWS (EKS) | GCP (GKE) | Azure (AKS) |
| --- | --- | --- | --- |
| Secret store | `secretstore-aws.yaml` (IRSA) | `secretstore-gcp.yaml` (Workload Identity) | `secretstore-azure.yaml` (Workload Identity) |
| Managed Postgres | RDS / Aurora PostgreSQL | Cloud SQL for PostgreSQL | Azure Database for PostgreSQL |
| Managed Redis | ElastiCache / MemoryDB | Memorystore for Redis | Azure Cache for Redis |
| `replayPersistence.storageClassName` | `gp3` | `premium-rwo` | `managed-csi` |
| `ingress.*.className` | `alb` | `gce` | `azure-application-gateway` |
| Ingress annotations | ALB scheme/target-type | GCE managed cert or cert-manager | AGIC annotations |

Keep `networkPolicy.allowOpenDns` and `allowOpenHttps` `false`; set `dnsEgress` and `extraEgress` to the named CIDRs of your managed Postgres, Redis, identity provider, and provider APIs.

## Upgrades and Rollback

Caracal database migrations are forward-only by design. Plan upgrades as roll-forward changes and only roll back application images when they remain schema-compatible. See [Upgrade Caracal](/operations/upgrade/).

## Why No Terraform Module

Caracal ships standardized, portable interfaces — External Secrets Operator, cert-manager, and the Helm chart — rather than per-cloud infrastructure-as-code modules. This keeps the deployment surface agnostic and avoids coupling Caracal to a single provider's resource model. Use your own IaC to provision the managed Postgres, Redis, secret manager, and cluster, then apply these artifacts.

## Validation

1. Confirm the `ExternalSecret` reports `SecretSynced` and `caracal-runtime` exists.
2. Render manifests and confirm no plaintext secret is present.
3. Confirm cert-manager issued the Gateway and API TLS certificates.
4. Confirm the `ServiceMonitor` is scraped and `PrometheusRule` alerts are loaded.
5. Run a canary token exchange and a Gateway-protected request, then confirm audit evidence.

## Next Step

Use [Harden Production](/operations/tls-hardening/) before opening external API or Gateway ingress to production traffic.
