Terragrunt for Beginners

Terragrunt Basic Concepts

The DRY Principle

In Infrastructure as Code (IaC), the DRY (Don’t Repeat Yourself) principle is essential for creating modular, maintainable, and scalable configurations. Terragrunt extends Terraform by enforcing DRY across your codebase. In this guide, you’ll learn how to:

  • Structure reusable modules to eliminate redundancy
  • Centralize and abstract variables for consistency
  • Inherit shared settings through a hierarchical layout
  • Streamline maintenance and promote changes safely

Note

This article assumes basic familiarity with Terraform and HCL. For a Terraform refresher, see Terraform Overview.


1. Modular Configuration

By encapsulating common resources in Terragrunt modules, you define infrastructure blocks once and reuse them across environments. This approach reduces code duplication and speeds up delivery.

Example module call in your environment folder:

# live/prod/app/terragrunt.hcl
include {
  path = find_in_parent_folders()
}

terraform {
  source = "git::ssh://[email protected]/your-org/terraform-modules.git//app?ref=v1.2.0"
}

inputs = {
  instance_count = 3
  instance_type  = "t3.medium"
}

The image illustrates the "Don't Repeat Yourself" (DRY) principle, highlighting modular configuration, modular and reusable components, and reduced redundancy.


2. Variable Abstraction

Terragrunt centralizes variable definitions into shared files, preventing hard-coded values and scattered overrides. Reuse a single variables.hcl across modules:

# live/common/variables.hcl
locals {
  project_name = "MyApp"
  region       = "us-east-1"
  tags = {
    Environment = read_terragrunt_config(find_in_parent_folders("env.hcl")).inputs.environment
    Project     = local.project_name
  }
}

Then reference it:

# live/prod/app/terragrunt.hcl
dependency "vars" {
  config_path = find_in_parent_folders("common")
}

inputs = merge(dependency.vars.outputs, {
  service_port = 8080
})

The image explains the "Don't Repeat Yourself" (DRY) principle, highlighting variable abstraction to avoid code repetition and enable centralized variable management.


3. Hierarchical Configuration Inheritance

Terragrunt’s directory structure supports inheritance of configuration blocks. Define global settings at the root, then override or extend them in child folders:

# live/terragrunt.hcl (root)
remote_state {
  backend = "s3"
  config = {
    bucket = "my-tf-state"
    key    = "${path_relative_to_include()}/terraform.tfstate"
    region = "us-east-1"
  }
}
# live/prod/terragrunt.hcl
include {
  path = find_in_parent_folders()
}

inputs = {
  environment = "production"
}

The image explains the "Don't Repeat Yourself" (DRY) principle, highlighting hierarchical configuration, enabling inheritance of settings, reducing duplicate configurations, and facilitating reuse of configuration settings.


4. Simplified Maintenance and Promotion

With DRY in place, updating modules or variables in one location propagates changes everywhere they’re used. This reduces configuration drift, lowers the risk of errors, and accelerates promotions across dev, staging, and prod.

BenefitDescriptionExample Change
Single Source of TruthOne module or file manages multiple environmentsBump AMI ID in module repository
Consistent Environment TagsCentral tags applied automatically across all deploymentsAdd CostCenter tag in variables.hcl
Rapid RolloutApply changes once and run terragrunt apply-allSecurity patch update
Reduced Human ErrorFewer manual edits across multiple HCL filesFix input typo in shared file

The image illustrates the "Don't Repeat Yourself" (DRY) principle, highlighting benefits like simplified maintenance, more maintainable code, and uniform updates across code.


Watch Video

Watch video content

Previous
What Problems Does Terragrunt Solve