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
doctest — The Fastest Feature-Rich C++ Testing Framework
doctest is a single-header C++ testing framework designed for minimal compile-time overhead and maximum speed.
Chai — BDD/TDD Assertion Library for Node.js
Chai is a flexible assertion library for Node.js and browsers that supports expect, should, and assert styles.
Supertest — HTTP Assertion Library for Node.js APIs
Supertest provides a high-level API for testing HTTP servers in Node.js with fluent assertion chaining.