ScriptsApr 15, 2026·3 min read

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.

TL;DR
Terragrunt wraps Terraform/OpenTofu to eliminate repeated config, manage remote state, and run dependent modules in parallel.
§01

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.

§02

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.

§03

How to use

  1. Install Terragrunt:
brew install terragrunt
  1. Create a root terragrunt.hcl with shared configuration:
remote_state {
  backend = "s3"
  config = {
    bucket = "my-terraform-state"
    key    = "${path_relative_to_include()}/terraform.tfstate"
    region = "us-east-1"
  }
}
  1. In each module directory, create a terragrunt.hcl that includes the parent:
include "root" {
  path = find_in_parent_folders()
}
  1. Run all modules:
terragrunt run-all apply
§04

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.

§05

Related on TokRepo

  • DevOps tools -- Explore other infrastructure and deployment automation tools
  • Automation tools -- Browse tools for CI/CD and workflow automation
§06

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-json to see the final configuration.
  • run-all commands can be dangerous. Running terragrunt run-all destroy without the --terragrunt-exclude-dir flag will destroy all infrastructure in the tree. Always use run-all plan before run-all apply.
  • Terragrunt caches downloaded modules in .terragrunt-cache. This directory can grow large over time. Add it to .gitignore and clean it periodically.

Frequently Asked Questions

Does Terragrunt work with OpenTofu?+

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.

What is the difference between Terragrunt and Terraform workspaces?+

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.

Can Terragrunt manage dependencies between modules?+

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.

How does Terragrunt handle remote state locking?+

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.

Is Terragrunt compatible with Terraform Cloud?+

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)

Discussion

Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.

Related Assets