# Terragrunt with OpenTofu: Keep Your Configuration DRY

> What Terragrunt is and how to use it with OpenTofu or Terraform to avoid repeating backend and provider code across environments, with a complete AWS example.

- Source: https://www.itwonderlab.com/terragrunt-opentofu/
- Published: 2026-02-19
- Updated: 2026-02-19
- Author: Javier Ruiz Jiménez (https://www.javierruizjimenez.com/)
- Site: IT Wonder Lab (https://www.itwonderlab.com/)

---

## What Terragrunt adds

[Terragrunt](https://terragrunt.gruntwork.io/) is a thin wrapper around OpenTofu and Terraform. It does not replace them: it calls `tofu` or `terraform` for you and solves three recurring problems of a multi-environment setup:

1. **Repeated code.** Every directory needs the same `backend` and `provider` blocks.
2. **Dependencies between configurations.** The application needs the network outputs, so the network must be applied first.
3. **Running many configurations at once.** `terragrunt run-all apply` (or the `run --all` form in recent versions) applies the whole tree in dependency order.

### Installation and configuration for OpenTofu

Install Terragrunt from its [releases page](https://github.com/gruntwork-io/terragrunt/releases) or with a package manager, and tell it to use OpenTofu:

```shell
$ export TG_TF_PATH=tofu
$ terragrunt --version
```

Terragrunt's command line and file names have changed across versions (for example, `terragrunt.hcl` can also be named `root.hcl`, and `run-all` has a newer `run --all` form), so confirm them in the documentation of your version.

### Directory layout

```
infra/
  root.hcl                      # shared backend and provider
  modules/
    network/
    app/
  live/
    dev/
      network/terragrunt.hcl
      app/terragrunt.hcl
    pro/
      network/terragrunt.hcl
      app/terragrunt.hcl
```

The modules are plain OpenTofu modules ([project structure](https://www.itwonderlab.com/terraform-project-structure/)). The `live` tree contains only Terragrunt configuration with the inputs of each environment.

### Root configuration

```hcl title="root.hcl"
locals {
  env = basename(dirname(path_relative_to_include()))
}

remote_state {
  backend = "s3"

  generate = {
    path      = "backend.tf"
    if_exists = "overwrite_terragrunt"
  }

  config = {
    bucket         = "ditwl-tfstate-${get_aws_account_id()}"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "eu-west-1"
    encrypt        = true
    dynamodb_table = "ditwl-tfstate-lock"
  }
}

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "aws" {
  region = "eu-west-1"
}
EOF
}
```

Every configuration gets its own state key and the same backend, with no copy-and-paste. (Newer versions of the S3 backend can lock with a file in S3 instead of DynamoDB; see [backends](https://www.itwonderlab.com/aws-terraform-tutorial-terraform-backends/).)

### Network and application with dependencies

```hcl title="live/pro/network/terragrunt.hcl"
include "root" {
  path = find_in_parent_folders("root.hcl")
}

terraform {
  source = "../../../modules/network"
}

inputs = {
  vpc_cidr = "10.10.0.0/16"
}
```

```hcl title="live/pro/app/terragrunt.hcl"
include "root" {
  path = find_in_parent_folders("root.hcl")
}

terraform {
  source = "../../../modules/app"
}

dependency "network" {
  config_path = "../network"

  mock_outputs = {
    private_subnet_ids = ["subnet-00000000"]
  }
}

inputs = {
  subnet_ids = dependency.network.outputs.private_subnet_ids
}
```

`dependency` reads the outputs of the network configuration and guarantees the apply order. The `mock_outputs` let `plan` and `validate` work before the network exists.

### Commands

```shell
$ cd live/pro/network
$ terragrunt plan
$ terragrunt apply

$ cd live/pro
$ terragrunt run-all plan      # every configuration in dependency order
```

### When to use it

Terragrunt is worth it when you have several environments, regions or accounts and many small states. For one or two environments, plain [directories](https://www.itwonderlab.com/terraform-workspaces-vs-directories/) and modules are enough and have one tool less to learn. Compare also with the dependency approach in [data sources and remote state](https://www.itwonderlab.com/terraform-data-sources-remote-state/).
