How to use Terragrunt to manage Terraform config

Updated: February 3, 2024 By: Guest Contributor Post a comment

Introduction

For developers working with infrastructure as code, managing complexity and avoiding duplication can be challenging as projects grow. Terragrunt is a thin wrapper that provides extra tools for keeping your Terraform configurations DRY (Don’t Repeat Yourself), working with multiple Terraform modules, and managing remote state more easily. In this guide, we’ll walk through how to use Terragrunt to simplify your Terraform configuration management, from basic to advanced use cases, along with code examples and outputs where applicable.

Getting Started with Terragrunt

Before diving into Terragrunt, make sure you have both Terraform and Terragrunt installed. Terragrunt is designed to work with all Terraform versions but it’s always good practice to keep both tools up to date. The installation instructions for each platform are available on the respective websites of Terraform and Terragrunt.

Once installed, the simple structure of a Terragrunt configuration looks something like this:

terraform {
  source = "./modules"
}

include {
  path = find_in_parent_folders()
}

inputs = {
  name = "example-project"
}

This configuration tells Terragrunt where to find the Terraform modules it should use (`source`) and allows it to inherit configuration from parent folders (`include`), a powerful feature for managing configurations across environments. In the `inputs` section, you define variables specific to this configuration.

Organizing Your Infrastructure with Terragrunt

One of the main advantages of Terragrunt is its ability to keep your infrastructure code DRY. By using the `include` block and the `find_in_parent_folders()` function, you can have a single terragrunt.hcl file in a root directory that defines common settings for all of your Terraform projects, reducing repetition.

// base/terragrunt.hcl
remote_state {
  backend = "s3"
  config = {
    bucket         = "my-terraform-state-bucket"
    key            = "${path_relative_to_include()}/${terraform.workspace}/terraform.state"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

Working with Multiple Environments

Managing multiple environments (development, staging, production) is where Terragrunt really shines. By creating directories for each environment and placing a terragrunt.hcl file in each one, you can customize configurations per environment while inheriting shared settings from a parent configuration.

// environments/dev/terragrunt.hcl
terraform {
  source = "../../modules/vpc"
}

include {
  path = find_in_parent_folders()
}

inputs = {
  environment = "dev"
  vpc_cidr = "10.0.0.0/16"
}

Advanced Configuration with Terragrunt

For more advanced use cases, Terragrunt allows you to leverage Terraform’s ability to call external data sources or use hooks to execute scripts before or after Terraform commands. For instance, a before_hook could be used to lint Terraform files before applying them.

before_hook "terraform_fmt" {
  commands     = ["apply", "plan"]
  execute      = ["terraform", "fmt", "-check"]
}

Importing Remote State

Another powerful feature of Terragrunt is the ability to easily import remote state from various backends, simplifying state management across multiple Terraform executions and projects. Below example demonstrates accession of a state file stored in S3:

dependency {
  name = "vpc"
  config_path = "../vpc"
}

inputs = {
  vpc_id = dependency.vpc.outputs.vpc_id
}

By referring to another Terragrunt configuration as a dependency, you can dynamically read its outputs and use them in your configuration.

Conclusion

Using Terragrunt to manage your Terraform configurations can significantly reduce complexity and duplication in your infrastructure code. By following the practices outlined in this guide, you can streamline your infrastructure management process, making it more maintainable and scalable. Whether you’re managing a single project or multiple environments, Terragrunt offers tools and features that enhance Terraform’s capabilities, making infrastructure as code even more powerful.