| name | terragrunt-generator |
| description | Comprehensive toolkit for generating best-practice Terragrunt configurations (HCL files) following current standards and conventions. Generates terragrunt.hcl files, root configurations, child modules, stacks, and environment setups; configures remote state backends, dependency blocks, include blocks, feature flags, exclude blocks, and errors blocks; supports DRY Terraform patterns, multi-environment layouts (dev/staging/prod), and OpenTofu engine integration. Use when creating new Terragrunt projects or resources, scaffolding multi-environment infrastructure, implementing DRY Terraform wrapper configurations, setting up terragrunt.hcl files with remote state or provider config, managing module dependencies, or building infrastructure modules with Terragrunt stacks. |
Terragrunt Generator
Overview
Generate production-ready Terragrunt configurations following current best practices, naming conventions, and security standards. All generated configurations are automatically validated.
Terragrunt 2025 Features Supported:
- Stacks - Infrastructure blueprints with
terragrunt.stack.hcl (GA since v0.78.0)
- Feature Flags - Runtime control via
feature blocks
- Exclude Blocks - Fine-grained execution control (replaces deprecated
skip)
- Errors Blocks - Advanced error handling (replaces deprecated
retryable_errors)
- OpenTofu Engine - Alternative IaC engine support
Root Configuration Naming
RECOMMENDED: Use root.hcl instead of terragrunt.hcl for root files per migration guide.
| Approach | Root File | Include Syntax |
|---|
| Modern | root.hcl | find_in_parent_folders("root.hcl") |
| Legacy | terragrunt.hcl | find_in_parent_folders() |
Architecture Patterns
CRITICAL: Before generating ANY configuration, determine the architecture pattern and understand its constraints.
Pattern Selection
| Pattern | Use When | Root Behavior | Structure |
|---|
| A: Multi-Env Agnostic | Multiple environments with shared root | Root reads NO env files; uses static values or get_env() | root.hcl + {env}/env.hcl per environment |
| B: Single/Env-Aware | Single environment OR environment detection needed | Root can parse path or read get_env() | root.hcl with optional account.hcl/region.hcl |
| C: Centralized Vars | Shared environment definitions | Root is agnostic; env.hcl reads from _env/ | root.hcl + _env/{env}.hcl + {env}/env.hcl |
Pattern A: Multi-Environment Agnostic Root
Key principle: root.hcl does NOT read env.hcl. Child modules read env.hcl directly.
infrastructure/
โโโ root.hcl # Environment-AGNOSTIC
โโโ dev/env.hcl # locals { environment = "dev" }
โ โโโ vpc/terragrunt.hcl
โโโ prod/env.hcl # locals { environment = "prod" }
โโโ vpc/terragrunt.hcl
Child module pattern:
include "root" { path = find_in_parent_folders("root.hcl") }
locals { env = read_terragrunt_config(find_in_parent_folders("env.hcl")) }
inputs = { name = "${local.env.locals.environment}-vpc" }
Pattern B: Environment-Aware Root
Key principle: Root detects environment from path or environment variable.
# root.hcl
locals {
path_parts = split("/", path_relative_to_include())
environment = local.path_parts[0] # OR: get_env("TG_ENVIRONMENT", "dev")
}
Pattern C: Centralized Variables
Key principle: Each env.hcl reads from centralized _env/{env}.hcl.
# prod/env.hcl
locals {
env_vars = read_terragrunt_config("${get_repo_root()}/_env/prod.hcl")
environment = local.env_vars.locals.environment
aws_region = local.env_vars.locals.aws_region
}
Decision: Multi-env + shared root โ A | Single env / env detection โ B | Centralized vars โ C
Core Capabilities
1. Generate Root Configuration
Create root-level root.hcl or terragrunt.hcl with remote state, provider config, and common variables.
Read before generating: assets/templates/root/terragrunt.hcl
Patterns: references/common-patterns.md โ Root Configuration Patterns
Key placeholders to replace:
[BUCKET_NAME], [AWS_REGION], [DYNAMODB_TABLE]
[TERRAFORM_VERSION], [PROVIDER_NAME], [PROVIDER_VERSION]
[ENVIRONMENT], [PROJECT_NAME]
Root.hcl Design Principles:
- Environment-agnostic by default โ Don't assume env.hcl exists at root level
- Use static values for provider/backend region โ Or
get_env() for runtime config
- State key uses
path_relative_to_include() โ Automatically includes environment path
- Provider tags can be static โ Environment-specific tags go in child modules
2. Generate Child Module Configuration
Create child modules with dependencies, mock outputs, and proper includes.
Read before generating: assets/templates/child/terragrunt.hcl
Patterns: references/common-patterns.md โ Child Module Patterns
Module source options:
- Local:
"../../modules/vpc"
- Git:
"git::https://github.com/org/repo.git//path?ref=v1.0.0"
- Registry:
"tfr:///terraform-aws-modules/vpc/aws?version=5.1.0"
3. Generate Standalone Module
Self-contained modules without root dependency.
Read before generating: assets/templates/module/terragrunt.hcl
4. Generate Multi-Environment Infrastructure
Complete directory structures for dev/staging/prod.
Before generating:
- Determine architecture pattern (see Architecture Patterns section)
- Read relevant templates for root and child modules
- Verify env.hcl placement and access patterns
Patterns: references/common-patterns.md โ Environment-Specific Patterns
Typical structure (Pattern A):
infrastructure/
โโโ root.hcl # Environment-AGNOSTIC root config
โโโ dev/
โ โโโ env.hcl # Dev environment variables
โ โโโ vpc/terragrunt.hcl
โโโ prod/
โโโ env.hcl # Prod environment variables
โโโ vpc/terragrunt.hcl
5. Generate Terragrunt Stacks (2025)
Infrastructure blueprints using terragrunt.stack.hcl.
Read before generating: assets/templates/stack/terragrunt.stack.hcl and assets/templates/catalog/terragrunt.hcl
Docs: Stacks Documentation
Patterns: references/common-patterns.md โ Stacks Patterns
Commands:
terragrunt stack generate
terragrunt stack run plan
terragrunt stack run apply
terragrunt stack output
terragrunt stack clean
6. Generate Feature Flags (2025)
Runtime control without code changes.
Docs: Feature Flags Documentation
Patterns: references/common-patterns.md โ Feature Flags Patterns
CRITICAL: Feature flag default values MUST be static (boolean, string, number) โ they CANNOT reference local.* values.
# Correct: static default
feature "enable_monitoring" {
default = false
}
# Incorrect: dynamic reference โ FAILS
feature "enable_monitoring" {
default = local.env.locals.enable_monitoring
}
Usage:
terragrunt apply --feature enable_monitoring=true
export TG_FEATURE="enable_monitoring=true"
7. Generate Exclude Blocks (2025)
Fine-grained execution control (replaces deprecated skip).
Docs: Exclude Block Reference
Patterns: references/common-patterns.md โ Exclude Block Patterns
Actions: "plan", "apply", "destroy", "all", "all_except_output"
Production recommendation: Protect critical resources from accidental destruction:
exclude {
if = true
actions = ["destroy"]
exclude_dependencies = false
}
prevent_destroy = true
8. Generate Errors Blocks (2025)
Advanced error handling (replaces deprecated retryable_errors).
Docs: Errors Block Reference
Patterns: references/common-patterns.md โ Errors Block Patterns
9. Generate OpenTofu Engine Configuration (2025)
Use OpenTofu as the IaC engine.
Docs: Engine Documentation
Patterns: references/common-patterns.md โ OpenTofu Engine Patterns
10. Handling Custom Providers/Modules
When generating configs with custom providers:
- Identify the provider name, source, and version
- Search using WebSearch:
"[provider] terraform provider [version] documentation"
- Or use Context7 MCP if available for structured docs
- Generate with proper
required_providers block
- Document authentication requirements in comments
Generation Workflow
CRITICAL: Follow this workflow for EVERY generation task. Skipping steps leads to validation errors.
Step 1: Understand Requirements
- What type of configuration? (root, child, standalone, stack)
- Single or multi-environment?
- What dependencies exist between modules?
- What providers/modules will be used?
Step 2: Determine Architecture Pattern and Complete Checklist
| Scenario | Pattern | Root.hcl Scope |
|---|
| Multi-env with shared root | Pattern A | Environment-agnostic |
| Single environment | Pattern B | Environment-aware |
| Centralized env vars | Pattern C | Environment-agnostic |
MANDATORY: Before writing any files, complete and output this checklist to the user.
## Architecture Pattern Selection
[x] Identified architecture pattern: Pattern ___ (A/B/C)
[x] Root.hcl scope: [ ] environment-agnostic OR [ ] environment-aware
[x] env.hcl location: ___________________
[x] Child modules access env via: ___________________
[x] Verified: No file references a path that doesn't exist from its location
Step 3: Read Required Templates
| Configuration Type | Template to Read |
|---|
| Root configuration | assets/templates/root/terragrunt.hcl |
| Child module | assets/templates/child/terragrunt.hcl |
| Standalone module | assets/templates/module/terragrunt.hcl |
| Stack file | assets/templates/stack/terragrunt.stack.hcl |
| Catalog unit | assets/templates/catalog/terragrunt.hcl |
Also read: references/common-patterns.md โ primary source for all generation patterns.
Step 4: Generate with Validation
Generation order for multi-environment projects:
-
Generate root.hcl first
-
Generate env.hcl files for each environment
-
Generate child modules โ modules with NO dependencies first
-
Generate dependent modules (RDS, EKS, etc.)
-
Run batch validation after ALL files are generated:
terragrunt hcl fmt --check
terragrunt dag graph
Invoke devops-skills:terragrunt-validator for comprehensive validation.
Step 5: Fix and Re-Validate
If validation fails:
- Analyze errors (path resolution, missing variables, syntax errors)
- Fix issues in the specific file(s)
- Re-validate the fixed file(s)
- Repeat until ALL errors are resolved
Step 6: Present Results
Follow the Presentation Requirements section below.
Validation Workflow
Every generated configuration MUST be validated.
Incremental Validation
After generating root.hcl:
cd <infrastructure-directory>
terragrunt hcl fmt --check
After generating each child module:
cd <module-directory>
terragrunt hcl fmt --check
terragrunt hcl validate --inputs
Full Validation
After all files are generated:
- Invoke
devops-skills:terragrunt-validator skill
- If validation fails: analyze errors, fix, and re-validate until all pass
- If validation succeeds: present configurations with usage instructions
Skip validation only for: Partial snippets, documentation examples, or explicit user request.
Presentation Requirements
After successful validation, present ALL of the following sections.
1. Directory Structure Summary
tree <infrastructure-directory>
2. Files Generated
| File | Purpose |
|------|---------|
| root.hcl | Shared configuration for all child modules (state backend, provider) |
| dev/env.hcl | Development environment variables |
| prod/env.hcl | Production environment variables |
| dev/vpc/terragrunt.hcl | VPC module for development |
| ... | ... |
3. Usage Instructions
## Usage Instructions
### Prerequisites
1. AWS credentials configured (`aws configure` or environment variables)
2. S3 bucket `<BUCKET_NAME>` exists for state storage
3. DynamoDB table `<TABLE_NAME>` exists for state locking
### Commands
cd <INFRASTRUCTURE_DIR>
terragrunt run --all init # Initialize all modules
cd <ENV>/vpc && terragrunt plan # Preview a specific module
terragrunt run --all plan # Preview all changes
terragrunt run --all apply # Apply changes (requires approval)
terragrunt run --all destroy # Destroy (use with extreme caution)
4. Environment-Specific Notes
## Environment Notes
### Required Environment Variables
| Variable | Description | Example |
|----------|-------------|---------|
| AWS_PROFILE | AWS CLI profile to use | `my-profile` |
| AWS_REGION | AWS region (or set in provider) | `us-east-1` |
### Prerequisites
- [ ] S3 bucket `<BUCKET_NAME>` must exist before first run
- [ ] DynamoDB table `<TABLE_NAME>` must exist for state locking
- [ ] IAM permissions for Terraform state management
### Production-Specific Protections
| Module | Protection | Description |
|--------|------------|-------------|
| prod/rds | `prevent_destroy = true` | Prevents accidental database deletion |
| prod/rds | `exclude { actions = ["destroy"] }` | Blocks destroy commands |
5. Next Steps (Optional)
Suggest what the user might want to do next (add more modules, customize configurations, etc.)
Best Practices
Reference ../devops-skills:terragrunt-validator/references/best_practices.md for comprehensive guidelines.
Key principles:
- Use
include blocks to inherit root configuration (DRY)
- Always provide mock outputs for dependencies
- Enable state encryption (
encrypt = true)
- Use
generate blocks for provider configuration
- Specify bounded version constraints (
~> 5.0, not >= 5.0) for local/Git modules
- Never hardcode credentials or secrets
- Configure retry logic for transient errors
Note on Version Constraints with Registry Modules: When using Terraform Registry modules (e.g., tfr:///terraform-aws-modules/vpc/aws?version=5.1.0), they typically define their own required_providers. Omit generating required_providers in root.hcl to avoid conflicts โ the module's pinned version provides the constraint.
Anti-patterns to avoid:
- Hardcoded account IDs, regions, or environment names
- Missing mock outputs for dependencies
- Duplicated configuration across modules
- Unencrypted state storage
- Missing or loose version constraints (except when using registry modules that define their own)
- Root.hcl trying to read env.hcl that doesn't exist at root level
Deprecated Attributes
Common Issues
For troubleshooting guidance, see references/troubleshooting.md, which covers:
- Root.hcl cannot find env.hcl errors
- Provider conflicts with registry modules
- Feature flag validation errors
- Child module env.hcl resolution issues
Anti-Patterns
NEVER use path_relative_to_include() as a module source path
- WHY: This function returns a path relative to the INCLUDING file, not the included root file; using it as a module source creates path resolution failures that vary by directory depth.
- BAD:
source = "..//${path_relative_to_include()}" in a child module's terraform.source.
- GOOD: Use
get_parent_terragrunt_dir() or construct explicit relative paths from the root terragrunt.hcl location.
NEVER duplicate backend configuration in every unit's terragrunt.hcl
- WHY: Copy-pasted
remote_state {} blocks drift across units over time, creating inconsistent state key schemes and locking configurations that are difficult to audit.
- BAD: A full
remote_state { backend = "s3" ... } block repeated in every leaf module.
- GOOD: Define remote state once in the root
root.hcl and inherit it in every unit via include "root" { path = find_in_parent_folders("root.hcl") }.
NEVER ignore dependency output mismatches between plan and apply
- WHY: When a
dependency.outputs reference is evaluated and the dependency has not been applied, Terragrunt substitutes mock_outputs silently; if mock types differ from actual output types, the apply will fail with a type error.
- BAD: Leave
mock_outputs blocks with placeholder types and dismiss mock_outputs substitution warnings during terragrunt plan.
- GOOD: Define
mock_outputs whose types exactly match the actual dependency outputs, and use mock_outputs_allowed_terraform_commands = ["validate", "plan"] to limit substitution scope.
NEVER run terragrunt run --all apply without awareness of external dependency scope
- WHY: By default, units outside the current directory tree are excluded from
run --all operations, which can produce partial applies that leave infrastructure in an inconsistent state.
- BAD: Run
terragrunt run --all apply from a subdirectory expecting all transitive dependencies to be included automatically.
- GOOD: Run from the repository root or pass
--terragrunt-include-external-dependencies explicitly to ensure the full dependency graph is evaluated.
NEVER use the same terragrunt.hcl for both dev and prod environments without environment-level variable overrides
- WHY: Sharing configuration without environment isolation causes prod deployments to silently inherit dev defaults (instance sizes, replica counts, retention policies).
- BAD: A single
terragrunt.hcl with no inputs block differentiation between environments.
- GOOD: Use environment-level
env.hcl files with inputs = { environment = "prod", instance_type = "m5.xlarge" } overrides that layer on top of shared defaults from the root configuration.
References
Templates โ Read Before Generating
| Configuration Type | Template File | When to Read |
|---|
| Root configuration | assets/templates/root/terragrunt.hcl | Before generating any root.hcl |
| Child module | assets/templates/child/terragrunt.hcl | Before generating any child module |
| Standalone module | assets/templates/module/terragrunt.hcl | Before generating standalone modules |
| Stack file | assets/templates/stack/terragrunt.stack.hcl | Before generating stacks |
| Catalog unit | assets/templates/catalog/terragrunt.hcl | Before generating catalog units |
References
| Reference | Content | When to Read |
|---|
references/common-patterns.md | All generation patterns with examples | Always, before generating |
references/troubleshooting.md | Common issues and fixes | When encountering errors |
../devops-skills:terragrunt-validator/references/best_practices.md | Comprehensive best practices | Always, before generating |
Official Documentation