Skip to content

Provision with OpenTofu

caracalHost renders cloud-init; it does not create a VM. caracalStack creates a namespace, optionally a Secret, and a Helm release; it does not create a cluster, Postgres, Redis, ingress controller, or secret manager.

Use OpenTofu >=1.8. Kubernetes also requires version >=1.30, kubeconfig access, external dependencies, and a complete runtime Secret.

  1. Copy the production tfvars example outside source control.
  2. Pin chartVersion, set database and Redis hosts, and deliver caracal-runtime before apply.
  3. Add reviewed chart overlays through extraValues.
  4. Run:
Terminal window
cd infra/tofu/envs/production
tofu init
tofu plan -out caracal.plan
tofu apply caracal.plan

The module waits for Jobs and uses atomic Helm behavior by default. Remote state and locking are operator responsibilities; never put plaintext runtime secrets in variables or state.

Attach caracalHost.userData or userDataBase64 to an operator-owned VM. It installs Docker when absent, installs a pinned release, writes non-secret overrides, and starts Caracal. Runtime secrets are generated on the host.

The packaged stack publishes every port on loopback, so a host without a proxy serves no external traffic. Set tlsProxy to terminate HTTPS in front of it:

tlsProxy = {
email = "ops@example.com"
routes = {
"console.example.com" = "web"
"sts.example.com" = "sts"
}
}

The console origin, the trusted-proxy flag, and the STS issuer are derived from these routes, so they cannot drift from the names the proxy terminates. Certificate issuance needs inbound 80 and 443 open in your cloud firewall, and every hostname must already resolve to the VM. proxyImage is pinned by digest; override it to track a different proxy.

Run bash infra/tofu/scripts/validate.sh in a checkout. After apply, verify Jobs, readiness, and audit evidence; on a VM run caracal status --ready. Use Helm revision rollback only when schema-compatible. Restore VM data and secrets separately before rebuilding.

Read Deploy with Helm or Deploy with Docker Compose.