Salta ai contenuti

Terragrunt Cheatsheet

Terragrunt Cheatsheet

Installation

PlatformCommand
macOS (Homebrew)brew install terragrunt
Linux (Binary)wget https://github.com/gruntwork-io/terragrunt/releases/download/v0.54.0/terragrunt_linux_amd64 && chmod +x terragrunt_linux_amd64 && sudo mv terragrunt_linux_amd64 /usr/local/bin/terragrunt
Windows (Chocolatey)choco install terragrunt
Windows (Scoop)scoop install terragrunt
Dockerdocker pull alpine/terragrunt:latest
Version Manager (tgenv)git clone https://github.com/cunymatthieu/tgenv.git ~/.tgenv && tgenv install latest
From Source (Go 1.21+)git clone https://github.com/gruntwork-io/terragrunt.git && cd terragrunt && go install
Verify Installationterragrunt --version

Basic Commands

CommandDescription
terragrunt initInitialize Terraform with backend configuration automatically managed
terragrunt planGenerate and show execution plan for infrastructure changes
terragrunt applyApply infrastructure changes (prompts for confirmation)
terragrunt apply -auto-approveApply changes without interactive confirmation
terragrunt destroyDestroy all managed infrastructure resources
terragrunt destroy -auto-approveDestroy resources without confirmation prompt
terragrunt validateValidate Terragrunt and Terraform configuration syntax
terragrunt fmtFormat Terraform configuration files to canonical style
terragrunt fmt -recursiveRecursively format all .tf files in subdirectories
terragrunt outputDisplay all output values from the state
terragrunt output <name>Display specific output value (e.g., terragrunt output vpc_id)
terragrunt output -jsonDisplay outputs in JSON format for parsing
terragrunt showDisplay current state or saved plan in human-readable format
terragrunt consoleOpen interactive console for testing expressions
terragrunt refreshUpdate state file with real infrastructure status
terragrunt state listList all resources tracked in the state file
terragrunt state show <resource>Show detailed state information for specific resource
terragrunt workspace listList all available workspaces
terragrunt workspace select <name>Switch to specified workspace
terragrunt workspace new <name>Create and switch to new workspace

Advanced Usage

CommandDescription
terragrunt run-all planExecute plan across all modules in dependency order
terragrunt run-all applyApply changes to all modules respecting dependencies
terragrunt run-all destroyDestroy all modules in reverse dependency order
terragrunt run-all initInitialize all modules in the directory tree
terragrunt run-all validateValidate all module configurations
terragrunt run-all outputDisplay outputs from all modules
terragrunt graph-dependenciesGenerate and display module dependency graph
terragrunt render-jsonRender final configuration as JSON for inspection
terragrunt hclfmtFormat terragrunt.hcl configuration files
terragrunt state mv <source> <dest>Move resource to different address in state
terragrunt state rm <resource>Remove resource from state without destroying it
terragrunt import <address> <id>Import existing infrastructure into Terraform state
terragrunt taint <resource>Mark resource for recreation on next apply
terragrunt untaint <resource>Remove taint marking from resource
terragrunt plan -out=tfplanSave execution plan to file for later apply
terragrunt apply tfplanApply previously saved plan file
terragrunt plan --terragrunt-log-level debugRun plan with detailed debug logging
terragrunt run-all apply --terragrunt-parallelism 3Limit parallel module execution to 3 concurrent operations
terragrunt apply --terragrunt-source ../local-moduleOverride module source for local development/testing
terragrunt run-all apply --terragrunt-include-dir vpcExecute only on specific module directories
terragrunt run-all apply --terragrunt-exclude-dir legacyExclude specific directories from execution
terragrunt apply --terragrunt-include-external-dependenciesInclude external dependencies in execution
terragrunt init -reconfigureReconfigure backend, ignoring existing configuration
terragrunt init -upgradeUpgrade provider plugins to latest allowed versions
terragrunt state pull > terraform.tfstateDownload and save remote state locally

Configuration

Basic terragrunt.hcl Structure

# Include root configuration
include "root" {
  path = find_in_parent_folders()
}

# Configure Terraform source
terraform {
  source = "git::https://github.com/org/terraform-modules.git//vpc?ref=v1.0.0"
}

# Define inputs (variables)
inputs = {
  environment    = "production"
  vpc_cidr       = "10.0.0.0/16"
  instance_type  = "t3.medium"
}

Remote State Configuration (Root terragrunt.hcl)

# Configure remote state backend
remote_state {
  backend = "s3"
  
  generate = {
    path      = "backend.tf"
    if_exists = "overwrite_terragrunt"
  }
  
  config = {
    bucket         = "my-terraform-state-${get_aws_account_id()}"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

Dependency Configuration

# Define dependencies between modules
dependency "vpc" {
  config_path = "../vpc"
  
  # Mock outputs for validation without dependencies applied
  mock_outputs = {
    vpc_id = "vpc-temporary-id"
  }
  
  mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}

# Use dependency outputs
inputs = {
  vpc_id = dependency.vpc.outputs.vpc_id
  subnet_ids = dependency.vpc.outputs.private_subnet_ids
}

Generate Provider Configuration

# Auto-generate provider configuration
generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  
  contents = <<EOF
provider "aws" {
  region = "us-east-1"
  
  default_tags {
    tags = {
      Environment = "${local.environment}"
      ManagedBy   = "Terragrunt"
    }
  }
}
EOF
}

Locals and Functions

# Define local variables
locals {
  environment = "production"
  region      = "us-east-1"
  
  # Parse environment from path
  parsed_path = regex(".*/environments/(?P<env>.*?)/.*", get_terragrunt_dir())
  env_name    = local.parsed_path.env
  
  # Common tags
  common_tags = {
    Environment = local.environment
    ManagedBy   = "Terragrunt"
    Project     = "MyProject"
  }
}

# Use locals in inputs
inputs = merge(
  local.common_tags,
  {
    region = local.region
  }
)

Hooks Configuration

# Execute commands before/after Terraform operations
terraform {
  before_hook "before_init" {
    commands = ["init"]
    execute  = ["echo", "Initializing Terraform..."]
  }
  
  after_hook "after_apply" {
    commands     = ["apply"]
    execute      = ["./scripts/notify-slack.sh"]
    run_on_error = false
  }
}

Common Use Cases

Use Case 1: Multi-Environment Infrastructure Setup

# Directory structure:
# └── environments/
#     ├── terragrunt.hcl (root config)
#     ├── dev/
#     │   ├── vpc/terragrunt.hcl
#     │   └── app/terragrunt.hcl
#     └── prod/
#         ├── vpc/terragrunt.hcl
#         └── app/terragrunt.hcl

# Deploy entire dev environment
cd environments/dev
terragrunt run-all apply

# Deploy only VPC in production
cd environments/prod/vpc
terragrunt apply

# Plan all production changes
cd environments/prod
terragrunt run-all plan

Use Case 2: Managing Module Dependencies

# In app/terragrunt.hcl, reference VPC dependency:
# dependency "vpc" {
#   config_path = "../vpc"
# }

# Apply app module (automatically applies VPC first if needed)
cd environments/dev/app
terragrunt apply --terragrunt-include-external-dependencies

# View dependency graph
cd environments/dev
terragrunt graph-dependencies | dot -Tpng > dependencies.png

Use Case 3: Local Module Development

# Override module source to test local changes
cd environments/dev/vpc
terragrunt plan --terragrunt-source ../../../modules/vpc-local

# Apply with local module
terragrunt apply --terragrunt-source ../../../modules/vpc-local

# Reset to remote source
terragrunt plan --terragrunt-source-update

Use Case 4: State Management and Migration

# List all resources in state
terragrunt state list

# Move resource to new address
terragrunt state mv aws_instance.old aws_instance.new

# Import existing AWS resource
terragrunt import aws_instance.web i-1234567890abcdef0

# Remove resource from state (keeps actual resource)
terragrunt state rm aws_instance.temporary

# Pull remote state for inspection
terragrunt state pull > backup.tfstate

Use Case 5: Debugging and Troubleshooting

# Enable debug logging
export TERRAGRUNT_LOG_LEVEL=debug
terragrunt plan

# Run with trace-level logging
terragrunt apply --terragrunt-log-level trace 2>&1 | tee debug.log

# Validate all configurations
terragrunt run-all validate

# Check formatting issues
terragrunt hclfmt --terragrunt-check

# Test configuration rendering
terragrunt render-json | jq '.'

Best Practices

  • Use DRY principle: Keep backend configuration in root terragrunt.hcl and include it in child modules using include blocks to avoid duplication
  • Version your modules: Always pin module sources to specific versions or tags (e.g., ?ref=v1.0.0) to ensure reproducible deployments
  • Implement dependency management: Use dependency blocks to explicitly define relationships between modules rather than relying on manual execution order
  • Leverage locals and functions: Use Terragrunt’s built-in functions like find_in_parent_folders(), get_aws_account_id(), and path_relative_to_include() for dynamic configuration
  • Use mock outputs: Define mock_outputs in dependency blocks to enable validation and planning without requiring all dependencies to be applied first
  • Organize by environment: Structure directories by environment (dev/staging/prod) with shared configuration at the root level for consistency
  • Enable state locking: Always configure DynamoDB tables for state locking when using S3 backend to prevent concurrent modification conflicts
  • Use run-all carefully: Test with run-all plan before run-all apply and consider using --terragrunt-parallelism to control concurrent executions
  • Generate provider configs: Use generate blocks to create provider configurations dynamically, ensuring consistency across modules
  • Implement hooks for automation: Use before_hook and after_hook to automate tasks like validation, notifications, or compliance checks

Troubleshooting

IssueSolution
Error: “No Terraform configuration files”Ensure terraform.source is correctly specified in terragrunt.hcl and the source path exists. Run terragrunt init to download modules.
Backend initialization failsCheck AWS credentials and permissions. Verify S3 bucket and DynamoDB table exist or set skip_bucket_creation = false in remote_state config.
Dependency outputs not foundEnsure dependency module is applied first. Use mock_outputs for planning without dependencies. Check config_path points to correct directory.
”Working directory already exists” errorClear Terragrunt cache: rm -rf .terragrunt-cache then run terragrunt init again. Or use --terragrunt-source-update flag.
Module source not updatingForce source update with terragrunt init --terragrunt-source-update or delete .terragrunt-cache directory to clear cached modules.
State lock acquisition timeoutAnother process holds the lock. Wait for completion or manually release lock in DynamoDB table. Check for crashed processes.
”Module not found” with relative pathsUse find_in_parent_folders() to locate root config. Ensure relative paths account for Terragrunt’s working directory structure.
Run-all commands fail partiallyCheck individual module errors with --terragrunt-log-level debug. Verify dependencies are correctly defined. Use --terragrunt-ignore-dependency-errors cautiously.
Permission denied errors on AWSVerify IAM role/user has required permissions. Check if role_arn in provider config is correct. Ensure MFA token is valid if required.
Circular dependency detectedReview dependency blocks to identify circular references. Restructure modules to break the cycle. Use terragrunt graph-dependencies to visualize.
Variables not being passed correctlyCheck inputs block syntax in terragrunt.hcl. Verify variable names match module definitions. Use terragrunt render-json to inspect final config.
Performance issues with many modulesAdjust --terragrunt-parallelism to optimize concurrent executions. Consider splitting into smaller module groups. Use --terragrunt-include-dir for selective runs.

Quick Reference: Terragrunt vs Terraform Commands

Terragrunt CommandEquivalent TerraformKey Difference
terragrunt initterraform initAuto-configures backend from terragrunt.hcl
terragrunt planterraform planIncludes Terragrunt-managed inputs and dependencies
terragrunt applyterraform applyProcesses dependencies and generates configs
terragrunt run-all applyN/AExecutes across multiple modules with dependency ordering
terragrunt outputterraform outputCan aggregate outputs from multiple modules