Terragrunt — DRY Orchestration Layer for Terraform & OpenTofu
Gruntwork's wrapper around Terraform/OpenTofu that keeps root modules DRY, manages multi-account state, and runs stacks in parallel.
What it is
Terragrunt is a thin orchestration layer built by Gruntwork that wraps Terraform and OpenTofu. It solves the DRY problem in infrastructure-as-code by letting you define shared configurations once and inherit them across environments. It also manages remote state backend configuration, dependency ordering between modules, and parallel execution of independent stacks.
Terragrunt is aimed at platform and DevOps engineers managing multi-account, multi-region infrastructure. If you find yourself copying the same backend configuration and provider blocks across dozens of Terraform root modules, Terragrunt eliminates that duplication.
How it saves time or tokens
Without Terragrunt, each Terraform root module needs its own backend config, provider config, and variable definitions -- even when they share 90% of the same values. Terragrunt's include and generate blocks let you define these once in a parent terragrunt.hcl and inherit them in child modules. When you change a shared setting, you update one file instead of fifty.
Dependency management is another time saver. Terragrunt reads dependency blocks to determine execution order and runs independent modules in parallel, reducing total apply time for large infrastructure changes.
How to use
- Install Terragrunt:
brew install terragrunt
- Create a root
terragrunt.hclwith shared configuration:
remote_state {
backend = "s3"
config = {
bucket = "my-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
}
}
- In each module directory, create a
terragrunt.hclthat includes the parent:
include "root" {
path = find_in_parent_folders()
}
- Run all modules:
terragrunt run-all apply
Example
# environments/prod/vpc/terragrunt.hcl
include "root" {
path = find_in_parent_folders()
}
terraform {
source = "../../../modules/vpc"
}
inputs = {
cidr_block = "10.0.0.0/16"
env_name = "prod"
}
dependency "account" {
config_path = "../account"
}
This module inherits remote state config from the root, sources the VPC Terraform module, passes environment-specific inputs, and declares a dependency on the account module.
Related on TokRepo
- DevOps tools -- Explore other infrastructure and deployment automation tools
- Automation tools -- Browse tools for CI/CD and workflow automation
Common pitfalls
- Terragrunt adds a layer of indirection. Debugging Terraform errors requires understanding both Terragrunt's generated configs and the underlying Terraform state. Use
terragrunt render-jsonto see the final configuration. run-allcommands can be dangerous. Runningterragrunt run-all destroywithout the--terragrunt-exclude-dirflag will destroy all infrastructure in the tree. Always userun-all planbeforerun-all apply.- Terragrunt caches downloaded modules in
.terragrunt-cache. This directory can grow large over time. Add it to.gitignoreand clean it periodically.
Frequently Asked Questions
Yes. Terragrunt supports both Terraform and OpenTofu. You can configure which binary to use via the terragrunt.hcl file or the TERRAGRUNT_TFPATH environment variable. OpenTofu is a drop-in replacement for Terraform, so existing Terragrunt configurations work without modification.
Terraform workspaces share the same configuration and state backend, switching between named states. Terragrunt uses separate directories per environment with inherited configuration, giving you full isolation between environments. Terragrunt is generally preferred for multi-account setups where environments need different providers or backends.
Yes. You declare dependencies using the dependency block in terragrunt.hcl. Terragrunt resolves the dependency graph and executes modules in the correct order. Independent modules run in parallel. You can also reference outputs from dependencies using dependency.outputs.
Terragrunt delegates state locking to the backend you configure (S3+DynamoDB, GCS, Azure Blob). It generates the backend configuration with proper locking settings. Terragrunt itself does not implement its own locking mechanism.
Partially. Terragrunt can generate Terraform Cloud backend configurations, but some features like run-all and dependency management work differently with remote execution. Many teams use Terragrunt with self-managed state backends (S3, GCS) rather than Terraform Cloud.
Citations (3)
- Terragrunt GitHub— Terragrunt is Gruntwork's wrapper for Terraform/OpenTofu
- Terragrunt Documentation— DRY configuration with include and generate blocks
- Terragrunt Dependencies— Dependency management and parallel execution
Related on TokRepo
Discussion
Related Assets
Heimdall — Application Dashboard for Your Server
Heimdall is an elegant self-hosted application dashboard that organizes all your web services and apps into a single, customizable start page with enhanced tile features.
Healthchecks — Cron Job Monitoring with Smart Alerts
Healthchecks is a self-hosted cron job and scheduled task monitor that alerts you when your periodic jobs fail to run on time.
Shiori — Simple Self-Hosted Bookmark Manager
Shiori is a lightweight self-hosted bookmark manager written in Go with full-text search, archiving, and a clean web interface for organizing your saved links.