Act 2 of the Terraform 101 workshop: the same multi-account story told
in terraform-101 (Act 1,
pure Terraform), re-expressed with Terragrunt to eliminate the
boilerplate, coupling, and manual orchestration Act 1 deliberately surfaced.
One-liner:
modules/(reusable, unchanged from Act 1) +live/(Terragrunt units, one state per leaf) + abootstrap/one-time step that creates the per-account state buckets — thenterragrunt run --all applyorchestrates the whole fleet in dependency order.
- Account → region → environment → category → resource hierarchy — the Gruntwork-recommended live layout for multi-account fleets
- Provider + backend generated once from
live/root.hcl— no hand-writtenprovider.tf/backend.tfanywhere allowed_account_idsguard on every generated provider — a mis-targeted profile fails before any API call- Typed
dependencyblocks replaceterraform_remote_state+ hardcoded state keys, withmock_outputsfor greenfield planning terragrunt run --all— one command to plan/apply/destroy the fleet in dependency order- Account baseline module — CloudTrail, AWS Config, GuardDuty, default EBS encryption per account (the P0 gap Act-1's critique flagged)
- Reuses the Act-1 modules byte-for-byte — the whole cure is in the orchestration layer
| Act-1 gap | Act-2 cure |
|---|---|
| 1. Boilerplate: provider + backend + module call copied into every root | root.hcl include + generate — provider/backend written once |
| 2. Static backend: bucket/key hardcoded per component | remote_state builds bucket + key = path_relative_to_include() from the unit's own path |
| 3. No single source of truth for region/profile/tags | account.hcl / region.hcl / env.hcl hierarchy, read via read_terragrunt_config(find_in_parent_folders(...)) |
4. Cross-component coupling via terraform_remote_state + hardcoded keys |
dependency blocks with typed outputs + mock_outputs for greenfield planning |
| 5. No orchestration: manual sequential applies | terragrunt run --all apply/plan/destroy with a real dependency DAG |
| 6. Bootstrap chicken-and-egg: state infra before state | bootstrap/ (local state, once) + Terragrunt auto-inits buckets; document remote_state.disable_init for fully-managed setups |
terragrunt-101/
├── bootstrap/ # ⚠ one-time, LOCAL state: create per-account state buckets
├── modules/ # ══ REUSABLE LAYER (unchanged from Act 1 + account-baseline) ══
│ ├── network/ # VPC, subnets, IGW, NAT, SGs
│ ├── database/ # RDS PostgreSQL (managed password)
│ ├── ecs/ # ECS cluster + Fargate + ALB
│ ├── state/ # S3 state bucket (bootstrap-only)
│ └── account-baseline/ # NEW: CloudTrail, Config, GuardDuty, EBS enc.
├── live/ # ══ LIVE LAYER (Terragrunt units) ══
│ ├── root.hcl # shared provider/backend generation, env assembly
│ ├── _envcommon/ # per-component shared inputs (exposed via include)
│ ├── dev/ # account-level: account.hcl
│ │ └── us-east-1/ # region-level: region.hcl
│ │ ├── _global/
│ │ │ └── account-baseline/
│ │ └── dev/ # environment-level: env.hcl
│ │ ├── networking/vpc/
│ │ ├── data-stores/postgres/
│ │ └── services/app/
│ ├── staging/ # (identical structure, different values)
│ └── prod/ # (identical structure, hardened values)
├── scripts/ # validate / plan helpers (offline-safe)
├── docs/ # RESEARCH-TERRAGRUNT, ARCHITECTURE, SETUP, DEMO-SCRIPT
└── .github/ # CI + issue templates + PR template
make check # hclfmt + static validation of every Terragrunt unit + tflint on modules# 1. One-time state bootstrap (local state — like Act 1)
cd bootstrap && terraform init && terraform apply
# 2. Deploy the entire dev account
cd live/dev
terragrunt run --all plan
terragrunt run --all apply
# 3. Deploy everything, everywhere
cd live
terragrunt run --all plan
terragrunt run --all apply- docs/ARCHITECTURE.md — repository architecture (layout, units, state, dependencies, execution model)
- docs/RESEARCH-TERRAGRUNT.md — the research: why Terragrunt, the enterprise pattern, sources
- docs/SETUP.md — credentials, OIDC, costs, teardown
- docs/DEMO-SCRIPT.md — the workshop narration (Act 1 → Act 2)
Contributions are welcome! Please read
CONTRIBUTING.md first. Report bugs and feature ideas
through the issue templates.
Found a vulnerability? Please report it privately — see
SECURITY.md. Do not open a public issue.