OpenTofu
OpenTofu is the open-source infrastructure-as-code engine that plans and applies the platform's modules: it reads the configuration, compares it with the recorded state and the cloud, and changes only the difference. The GCP Enterprise Baseline and the GCP Web App and Data and ETL Blueprints pin OpenTofu 1.12.6 and run it through Terragrunt.
What it does
A module is a folder of resources and variables. A provider is the plugin that talks to one API, here Google Cloud, Kubernetes or Helm. A plan shows the changes a configuration would make; an apply makes them and records the result in state, kept in a backend with a lock so two runs cannot write at once. Version constraints pin the engine and every provider so a run tomorrow behaves like a run today.
How BuiltForProd uses it
One engine version. Every root.hcl sets terraform_version_constraint = ">= 1.12.6, < 2.0.0", and the workflows install 1.12.6 (TF_VERSION) with the setup-opentofu action.
Providers. root.hcl generates each unit's versions.tf, the only place providers are pinned:
generate "versions" {
path = "versions.tf"
if_exists = "skip"
contents = <<-EOF
terraform {
required_version = ">= 1.12.6"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 8.5"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 8.5"
}
}
}
EOF
}
| Repository | Providers |
|---|---|
| GCP Enterprise Baseline | hashicorp/google and hashicorp/google-beta ~> 8.5; hashicorp/helm ~> 3.3 in github-runners |
| Web App Blueprint | hashicorp/google ~> 8.5; hashicorp/helm ~> 3.3 and hashicorp/kubernetes ~> 3.2 in the cluster modules |
| Data and ETL Blueprint | hashicorp/google and hashicorp/google-beta ~> 8.5 |
A module ships its own versions.tf only when it needs provider aliases or an extra provider, and then repeats the root pins exactly; scripts/check-module-versions.py fails a pull request that drifts. The generated provider blocks set user_project_override with the target project as billing project, so quota and billing land in the project being changed, and add every platform label as default_labels.
Modules. Every module is a thin local module: 31 in the Baseline, 10 in the Web App Blueprint and 5 in the Data and ETL Blueprint, with no registry modules. One module does one job (a VPC, a log bucket, a GKE cluster), and a unit instantiates it.
State. All repositories share one Cloud Storage bucket, acme-usw1-root-tfstate in the seed project, with OpenTofu's native locking and a prefix per unit; bucket IAM lets each repository identity write only its own prefix. Nothing in root.hcl calls gcloud or needs credentials to evaluate, so terragrunt stack generate, render and validate work offline.
Static checks. The plan workflow checks formatting with tofu fmt and runs tflint with the Google ruleset and Checkov; pre-commit adds tofu validate and Trivy; see Checkov, Trivy and tflint.
Terms you will see
| Term | Meaning |
|---|---|
| Provider | The plugin that talks to one API, such as hashicorp/google. |
~> 8.5 | Any 8.x release from 8.5 on, never 9.0. |
user_project_override | Bill and count quota against the project being changed. |
| State prefix | The folder in the state bucket that holds one unit's state. |
| Native locking | The lock file OpenTofu writes beside the state in Cloud Storage. |
Where to read more
- GCP Enterprise Baseline overview and its versions page.
- Terragrunt for how the units are generated and run.
- OpenTofu and Terraform for why the platform uses OpenTofu.