Foundations
Everything a Kubernetes API server needs to exist before Flux can reconcile anything — the network, the secrets and PKI layer, and the cluster itself — is provisioned with OpenTofu stacks orchestrated by Terramate. This page is the model: why these two tools, and why three stages rather than one. For the commands and what each stage actually creates, see Get Started and this section’s cloud-specific page.
Why OpenTofu
OpenTofu is the open-source fork of Terraform, created after HashiCorp moved
Terraform off an OSI-approved license. It is now a Linux Foundation project
with community governance, and it stayed compatible with existing Terraform
configuration and providers — so adopting it cost nothing beyond the tool
name in CI and mise.toml.
Why Terramate
A platform with five-plus independent lifecycles (network, secrets, cluster bootstrap split into two internal stages, an opt-in LLM platform) doesn’t fit one OpenTofu root module. Terramate turns the separate stacks into one graph:
- Ordering — each stack declares the stacks it runs
afterin itsstack.tm.hcl. Terramate topologically sorts the graph instead of a human remembering tocdinto five directories in the right sequence. - Drift detection —
terramate script run drift detectplans every stack and reports divergence without applying anything. - DRY configuration —
opentofu/config.tm.hclholds the globals every stack reads (region, cluster name, chart versions) instead of five copies of the same variable. - Opt-in gating — a stack tagged
opt-in(currentlyllm-platform) is skipped by default and pulled in with a tag filter or an environment variable, without a second orchestration mechanism next to this one.
The alternative — running tofu apply by hand in each stack directory —
still works; it just loses all four of the above and puts the ordering back
in a human’s head.
The three-stage model
Every cloud this platform targets provisions in the same three stages, because the dependency between them is real, not a convention:
- Network — VPC/subnets and whatever gives this machine private access to what gets built next. Nothing after this stage can reach anything built in the next two.
- Security — a secrets and PKI layer, running before Kubernetes exists
because Kubernetes bootstrap itself consumes it: on AWS, the second half
of cluster bootstrap reads an AppRole credential this stage already
created and seeds it into the cluster as a bootstrap Secret, so the
Kubernetes stack’s own
stack.tm.hcldeclares this stage in itsafterlist. - Kubernetes — the cluster, plus enough of a CNI to make nodes
Ready, with Flux installed and reconciling by the end of it. This is the handoff point: once Flux is running, GitOps owns everything that happens next.
This page stays cloud-neutral on purpose, not because there is one “true” shape underneath, but because the model — three stages, in this order, for this reason — really is the same on every cloud, while the stacks that implement it are not. Where a page can’t be honestly neutral, it isn’t: ADR-0007 makes the same call for the Crossplane compositions — an API that only looks cloud-neutral produces worse errors than one that is honestly cloud-shaped — so the cloud-specific detail lives on AWS (and eventually GCP), not blended in here.