Terragrunt Common Generation Patterns
This reference provides common patterns and code examples for generating Terragrunt configurations. Use these patterns as building blocks when creating new Terragrunt resources.
Overview
Terragrunt Common Generation Patterns
Overview
This reference provides common patterns and code examples for generating Terragrunt configurations. Use these patterns as building blocks when creating new Terragrunt resources.
Include syntax standard: Use
find_in_parent_folders("root.hcl")for new projects. Only usefind_in_parent_folders()when the repository intentionally keeps a legacy root file namedterragrunt.hcl.
Root Configuration Patterns
Pattern 1: Basic Root with S3 Backend
Use when: Starting a new Terragrunt project with AWS S3 backend
# root.hcl (modern root file name)
remote_state {
backend = "s3"
config = {
bucket = "company-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
}
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
provider "google" {
project = var.gcp_project
region = var.gcp_region
}
EOF
}
Child Module Patterns
Pattern 1: Simple Module with No Dependencies
Use when: Creating standalone infrastructure component
# modules/vpc/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "tfr:///terraform-aws-modules/vpc/aws?version=5.1.0"
}
inputs = {
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b", "us-east-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = false
tags = {
Name = "my-vpc"
}
}
Pattern 2: Module with Single Dependency
Use when: Creating a resource that depends on another module's outputs
# modules/rds/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "tfr:///terraform-aws-modules/rds/aws?version=6.1.0"
}
dependency "vpc" {
config_path = "../vpc"
mock_outputs = {
vpc_id = "vpc-mock123"
database_subnet_ids = ["subnet-mock1", "subnet-mock2"]
}
mock_outputs_allowed_terraform_commands = ["validate", "plan", "destroy"]
}
dependency "security_group" {
config_path = "../security-groups/database"
mock_outputs = {
security_group_id = "sg-mock123"
}
mock_outputs_allowed_terraform_commands = ["validate", "plan", "destroy"]
}
inputs = {
identifier = "mydb"
engine = "postgres"
vpc_security_group_ids = [dependency.security_group.outputs.security_group_id]
db_subnet_group_name = dependency.vpc.outputs.database_subnet_group_name
allocated_storage = 20
instance_class = "db.t3.micro"
}
Pattern 3: Module with Multiple Dependencies
Use when: Creating complex infrastructure with multiple upstream dependencies
# modules/eks/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "tfr:///terraform-aws-modules/eks/aws?version=19.15.0"
}
dependencies {
paths = ["../vpc", "../security-groups", "../iam-roles"]
}
dependency "vpc" {
config_path = "../vpc"
mock_outputs = {
vpc_id = "vpc-mock"
private_subnet_ids = ["subnet-1", "subnet-2"]
}
mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}
dependency "security_groups" {
config_path = "../security-groups"
mock_outputs = {
cluster_security_group_id = "sg-mock"
}
mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}
dependency "iam" {
config_path = "../iam-roles"
mock_outputs = {
cluster_role_arn = "arn:aws:iam::123456789012:role/mock-role"
}
mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}
inputs = {
cluster_name = "my-eks-cluster"
cluster_version = "1.28"
vpc_id = dependency.vpc.outputs.vpc_id
subnet_ids = dependency.vpc.outputs.private_subnet_ids
cluster_security_group_id = dependency.security_groups.outputs.cluster_security_group_id
iam_role_arn = dependency.iam.outputs.cluster_role_arn
enable_irsa = true
}
Pattern 4: Module with Conditional Logic
Use when: Generating configurations with environment-specific variations
# modules/app/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
locals {
env = get_env("ENVIRONMENT", "dev")
instance_counts = {
dev = 1
staging = 2
prod = 3
}
instance_types = {
dev = "t3.micro"
staging = "t3.small"
prod = "t3.medium"
}
}
terraform {
source = "../../terraform-modules/app"
}
inputs = {
environment = local.env
instance_count = local.instance_counts[local.env]
instance_type = local.instance_types[local.env]
enable_monitoring = local.env == "prod" ? true : false
enable_backups = local.env == "prod" ? true : false
tags = merge(
{
Environment = local.env
ManagedBy = "Terragrunt"
},
local.env == "prod" ? { CriticalResource = "true" } : {}
)
}
Environment-Specific Patterns
Pattern 1: Environment Configuration Files
Use when: Managing multiple environments with shared structure
infrastructure/
├── root.hcl # Root config (modern)
├── _env/
│ ├── prod.hcl # Production variables
│ ├── staging.hcl # Staging variables
│ └── dev.hcl # Development variables
├── prod/
│ ├── env.hcl -> ../_env/prod.hcl
│ └── vpc/
│ └── terragrunt.hcl
└── staging/
├── env.hcl -> ../_env/staging.hcl
└── vpc/
└── terragrunt.hcl
_env/prod.hcl:
locals {
environment = "prod"
region = "us-east-1"
vpc_cidr = "10.0.0.0/16"
instance_type = "t3.medium"
min_size = 3
max_size = 10
}
prod/vpc/terragrunt.hcl:
include "root" {
path = find_in_parent_folders("root.hcl")
}
locals {
env = read_terragrunt_config(find_in_parent_folders("env.hcl"))
}
terraform {
source = "tfr:///terraform-aws-modules/vpc/aws?version=5.1.0"
}
inputs = {
name = "${local.env.locals.environment}-vpc"
cidr = local.env.locals.vpc_cidr
azs = ["${local.env.locals.region}a", "${local.env.locals.region}b"]
}
Advanced Patterns
Pattern 1: Dynamic Provider Configuration
Use when: Provider configuration varies by module or environment
# modules/cross-account-resource/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
locals {
target_account_id = "987654321098"
}
generate "provider_override" {
path = "provider_override.tf"
if_exists = "overwrite"
contents = <= 1.3.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0" # Legacy version for compatibility
}
}
}
EOF
}
terraform {
source = "../../terraform-modules/legacy-resource"
}
Stacks Patterns (2025)
Terragrunt Stacks allow you to define infrastructure blueprints that generate unit configurations programmatically. GA since v0.78.0 (May 2025).
Pattern 1: Basic Stack with Units
Use when: Creating a reusable infrastructure blueprint
Catalog units expect values.name as the base resource identifier from each stack unit.
# terragrunt.stack.hcl
loca