Terragrunt
Terragrunt is a thin wrapper around OpenTofu that keeps many small configurations consistent: one place for the state backend and provider, dependencies between configurations, and a way to run them all in order. The platform uses Terragrunt 1.1.5 and its Stacks feature in all three infrastructure repositories.
What it does
A Terragrunt unit is a folder with a terragrunt.hcl that names a module, its inputs and its dependencies. A root configuration supplies what every unit shares. terragrunt run --all plan walks the dependency graph and plans every unit in order. With Stacks, units are no longer copied per environment: a stack file lists which unit definitions a folder deploys, and Terragrunt generates the concrete units on demand.
How BuiltForProd uses it
The layout is the same in the AWS Baseline and both infrastructure blueprints. The units and stacks concept page explains the ideas; this is where they live:
| Path | Holds |
|---|---|
units/<unit>/terragrunt.hcl | One definition per unit type. The module it uses, its dependencies with mock_outputs, and inputs that read per-stage data from values. |
stacks/<template>/terragrunt.stack.hcl | A template grouping units, such as webapp-stage (fourteen units) or the Baseline's plat-account (seven units), with try() defaults for every value. |
environments/<...>/terragrunt.stack.hcl | One per stage or account and region. Instantiates a template and sets only that stage's values, each tagged # TODO: or # @optional:. |
environments/**/.terragrunt-stack/ | The generated tree. Git-ignored, never edited by hand. |
root.hcl | Remote state, generated provider and version files, naming locals and tags. |
A generated unit's state key is its generated path with the .terragrunt-stack/ segments removed, so state keys are stable no matter how the files are laid out; the web application's EKS state, for example, is apps/app-blueprint/environments/dev/us-west-2/shared-infra/eks/terraform.tfstate.
Dependencies carry mock_outputs so every unit can be planned before its dependency exists. The argocd unit, for instance, depends on eks, external-secrets and acm-certificate-internal, and mocks the cluster endpoint, the secret store name and a certificate ARN. Four guard scripts keep the layout honest in pre-commit and CI: check-mock-outputs.py, check-stack-layout.py, check-module-versions.py and check-required-inputs.py.
Units read cross-repository data from Parameter Store rather than remote state: the Baseline publishes VPC and subnet ids, and blueprint modules look them up with data sources. That is what keeps each repository's state private to its team.
Terms you will see
| Term | Meaning |
|---|---|
| Unit | One deployable configuration: a module plus inputs and dependencies. |
| Stack file | A terragrunt.stack.hcl listing units or instantiating a template. |
| Values | The per-stage data a stack file hands to a unit definition. |
| Mock outputs | Placeholder dependency outputs that make a plan possible before apply. |
| Generated tree | The .terragrunt-stack/ folder Terragrunt writes from the stack file. |
Where to read more
- Terragrunt units and stacks
- OpenTofu for the engine underneath
- Release notes for the pinned versions
- Systems Manager Parameter Store for the cross-repository contract