Skip to content

Cloud Support Matrix

Caracal ships three deployment models. The stack itself is provider-neutral: the same released images, the same environment contract, the same schema migrations. Each model has a provider-neutral core and a small adapter per cloud, so a provider is a translation layer rather than a branch in the deployment logic. To add one, see Add a Cloud Provider.

ModelCoreAzureAWSGoogle Cloud
Virtual machinecaracalHost cloud-initSupportedExperimentalExperimental
Managed container platformcontainerPlatform topologySupported (Container Apps)Experimental (ECS on Fargate)Experimental (Cloud Run)
KubernetesHelm chartSupported (AKS overlay)Experimental (EKS overlay)Experimental (GKE overlay)

Supported means the adapter is implemented, validated in CI, and exercised against a live account. It is not a capacity, availability, or compliance claim.

Experimental means the adapter renders, validates against the provider’s own schema, and satisfies the shared contract, but has not been deployed to a live account. Azure is the reference implementation; treat the others as a starting point you verify in your own environment.

These hold on every cloud and every model, and no adapter may alter them:

  • The published images, with the container start command selecting the service role.
  • The environment and secret contract in Configuration Reference.
  • Expand-only schema migrations applied to completion before a rollout.
  • Postgres with migration privileges, and Redis with Streams and noeviction.
  • /health and /ready, and the same readiness semantics.

caracalHost renders cloud-init; a providers/<cloud>/host adapter creates the instance, its inbound exposure, its cloud identity, and its DNS records. Every adapter takes the same inputs and returns the same outputs, so changing cloud means changing a module source. Set tlsProxy on the core to terminate HTTPS and derive the console origin and token issuer from its routes.

ConceptAzureAWSGoogle Cloud
InstanceLinux virtual machineEC2 instanceCompute Engine instance
Public addressStatic public IPElastic IPStatic external address
Inbound exposureNetwork security groupSecurity groupVPC firewall rule
IdentityUser-assigned managed identityIAM role and instance profileAttached service account
DNSAzure DNS A recordRoute 53 recordCloud DNS record set

Caveat. The bootstrap installs Docker through get.docker.com, which supports Debian, Ubuntu, RHEL, and Fedora. It does not support Amazon Linux 2023 or Container-Optimized OS. The adapters use Ubuntu images; if you change the image, install the container runtime with extraRuncmd.

topology.yaml describes the deployment once; an adapter maps it onto a provider. Each adapter declares how its platform delivers secrets and how services address each other, and the core does the rest.

Neutral conceptAzure Container AppsAWS ECS on FargateGoogle Cloud Run
Role selectioncommand overrideentryPoint and commandcommand override
Secret deliveryProjected fileEnvironment variableEnvironment variable
Secret referenceKey Vault URL with a managed identitySecrets Manager ARN with a task roleSecret Manager version with a service account
Registry authManaged identity with AcrPullTask execution roleRuntime service account
Internal addresshttps://<app>.internal.<envDomain>Service Connect discovery nameInternal-ingress service URL
One-shot migrationContainer Apps JobTask definition run with RunTaskCloud Run Job
Autoscalinghttp concurrency ruleService desired countConcurrency and instance bounds
Durable spill storageNFS Azure Files shareEFS access pointNone available
Resource shapeFixed vCPU-to-memory ladder, 4 vCPU ceilingFargate task sizesUp to 8 vCPU and 32 GiB

Two consequences are worth knowing before choosing a provider:

  • Only Container Apps projects credentials as files. ECS cannot mount a secret at all, and Cloud Run refuses two secret volumes at one mount path, so neither can give a service the several credentials it needs as files. On both, credentials are bound to environment variables and resolved before the instance starts. They never appear in a task definition or service manifest, but a principal who can describe the running workload can read them; scope that permission accordingly.
  • Cloud Run has no durable per-instance volume. STS and Gateway spill audit evidence to disk when Redis is unreachable; on Cloud Run that evidence survives only while the instance lives.

The chart is cloud-neutral. Four values carry the entire provider surface:

ValueAKSEKSGKE
replayPersistence.storageClassNamemanaged-csigp3premium-rwo
ingress.*.classNamewebapprouting.kubernetes.azure.comalbgce
serviceAccount.annotationsazure.workload.identity/client-ideks.amazonaws.com/role-arniam.gke.io/gcp-service-account
global.podLabelsazure.workload.identity/use: "true"not requirednot required

infra/helm/caracal/examples carries a worked overlay for each. A cloud that needs a chart change is a bug in the chart.

The baseline migration creates the pgcrypto extension and six service roles, and grants CREATEDB to the role that owns the console’s auth database. Managed Postgres restricts all three, so confirm them before the first deployment on any provider. A migration job that fails here fails the whole rollout, by design.

RequirementAzure Database for PostgreSQLAmazon RDS and AuroraCloud SQL
pgcryptoMust be added to the azure.extensions server parameter first. CREATE EXTENSION fails until it is, and the parameter change needs a server restartAvailable to the master userAvailable to the default user
Create rolesAdministrative user is a member of azure_pg_adminMaster user holds rds_superuserDefault user holds cloudsqlsuperuser
Grant CREATEDBPermitted for the administrative userPermitted for the master userPermitted for the default user

Run the migration job against the managed instance before provisioning anything else. It is the cheapest possible failure and it exercises connectivity, TLS, credentials, and privileges in one step.

Use Choose a Deployment Profile to pick a model, then the workflow page for it: Docker Compose, a managed container platform, or Helm.