Skip to content

terraform

unit

Usage

The terraform block configures how Terragrunt runs OpenTofu/Terraform: where to get the module, which files to copy into the working directory, extra CLI arguments, and commands to run before and after tofu/terraform.

terragrunt.hcl
terraform {
source = "git::https://github.com/acme/modules.git//vpc?ref=v1.0.0"
extra_arguments "retry_lock" {
commands = get_terraform_commands_that_need_locking()
arguments = ["-lock-timeout=20m"]
}
before_hook "fmt" {
commands = ["apply", "plan"]
execute = ["tofu", "fmt", "-check"]
}
}

With a source, Terragrunt downloads the module into .terragrunt-cache, copies the unit’s directory into the same place, and runs tofu/terraform there. It skips hidden files and directories in the copy unless include_in_copy names them.

Module sources

A tfr:// source pulls a module from a module registry, in the form tfr://REGISTRY_HOST/MODULE_SOURCE[?version=VERSION]:

terragrunt.hcl
terraform {
source = "tfr://registry.opentofu.org/terraform-aws-modules/vpc/aws?version=3.3.0"
}
  • Without ?version= or a version attribute, Terragrunt downloads the latest stable version. Pin a version for reproducible runs.
  • tfr:/// with three slashes uses the default registry: registry.opentofu.org for OpenTofu, and registry.terraform.io for Terraform. When Terragrunt can’t tell which one it runs, it uses registry.opentofu.org. Set TG_TF_DEFAULT_REGISTRY_HOST to use another host.
  • // selects a submodule, e.g. tfr:///terraform-aws-modules/iam/aws//modules/iam-policy?version=4.3.0.
  • For a private registry, set TG_TF_REGISTRY_TOKEN to an API token for it.

An oci:// source pulls a module from an OCI registry, in the form oci://REGISTRY_HOST/REPOSITORY[//SUBDIR][?tag=TAG|?digest=DIGEST], e.g. oci://ghcr.io/acme/terraform-modules/vpc?tag=1.0.0. Without a tag or digest, Terragrunt uses the latest tag. See OCI registries.

Version constraints

The version attribute resolves a tfr:// source against the registry’s list of versions:

  • It applies to tfr:// sources only. Setting it with any other source is an error, and so is also setting ?version= in the source.
  • The --source flag and TG_SOURCE replace version along with source. They take an exact ?version= only, not a constraint.
  • Terragrunt checks the registry on every run, so it downloads a newly published version that satisfies the constraint without --source-update.
  • A prerelease qualifies only when the constraint names one, e.g. >= 2.0.0-rc1, as in OpenTofu/Terraform.

Hook commands

Besides tofu/terraform commands, a hook’s commands can name three stages of a Terragrunt run: terragrunt-read-config, init-from-module, and init. Running terragrunt plan on a unit with a source runs hooks in this order:

Diagram

When a stage fails, Terragrunt runs that stage’s after hooks that set run_on_error = true, then its error_hook blocks whose on_errors match the error. An error_hook with init-from-module catches download errors.

terragrunt-read-config and init-from-module hooks run in the unit’s directory, and other hooks in the directory Terragrunt runs OpenTofu/Terraform in.

A note about using modules from the registry

Terragrunt runs shared service modules as root modules. OpenTofu/Terraform modules fall into two groups:

  • A root module is one you run tofu init and tofu apply in directly. It has the blocks that configure OpenTofu/Terraform, such as backend and provider blocks.
  • A shared module is one other modules call through module blocks. It lacks those blocks.

Terragrunt splits shared modules in two:

Terragrunt generates the missing blocks to run a shared service module as a root module. Most registry modules are shared modules meant for composition, so Terragrunt can’t always deploy them. Two limitations block the conversion:

  • Every complex variable needs a type, or OpenTofu/Terraform reads the input Terragrunt passes as a string. This includes lists and maps.
  • Derived sensitive outputs must be marked sensitive. See sensitive variables.

If a registry module fails to deploy with Terragrunt, open an issue on the Terragrunt repository with the module and the error message, rather than on the module’s repository.

Attributes

sourceoptional(string)

Where to fetch the OpenTofu/Terraform module from. It takes the same syntax as an OpenTofu/Terraform module source, e.g. a local path or a Git URL with a ref, plus tfr:// registry sources and oci:// sources. Terragrunt downloads the whole repository, the part before //, so relative paths between modules in it keep working. See Module sources.

terragrunt.hcl
terraform {
source = "git::https://github.com/acme/modules.git//vpc?ref=v1.0.0"
}
versionoptional(string)

A version constraint for a tfr:// source, in the same syntax as the version argument of an OpenTofu/Terraform module block. Terragrunt downloads the highest published version that satisfies it. See Version constraints.

terragrunt.hcl
terraform {
source = "tfr://registry.opentofu.org/terraform-aws-modules/vpc/aws"
version = "~> 3.3"
}
include_in_copyoptional(list(string))

Glob patterns for files to copy into the OpenTofu/Terraform working directory that Terragrunt would otherwise skip, e.g. hidden files such as .python-version. Patterns are relative to the source directory. With the symlinks experiment, a pattern can name a symlinked directory, and Terragrunt copies the link target’s contents. It skips a link that points back at a directory it’s already copying, or at a parent of one, and logs a warning.

terragrunt.hcl
terraform {
source = "../modules/networking/vpc"
include_in_copy = [
".security_group_rules.json",
"*.yaml",
]
}
exclude_from_copyoptional(list(string))

Glob patterns for files in the unit’s directory that Terragrunt skips when it copies them into the OpenTofu/Terraform working directory. A file that matches both this and include_in_copy is skipped. To keep files from the module source out of the working directory, use a before_hook.

terragrunt.hcl
terraform {
source = "../modules/networking/vpc"
exclude_from_copy = ["*.md"]
}
copy_terraform_lock_fileoptional(bool, true)

Copies the .terraform.lock.hcl file from the OpenTofu/Terraform working directory back to the unit’s directory. Set it to false to keep the lock file out of the unit’s directory, e.g. when you don’t commit it. See Lock files.

terragrunt.hcl
terraform {
source = "../modules/networking/vpc"
copy_terraform_lock_file = false
}
no_dot_terragrunt_cacheoptional(bool, false)

Runs OpenTofu/Terraform in the unit’s directory instead of a copy in .terragrunt-cache. Files a run creates stay in the unit’s directory. Setting it with source or --source is an error. It needs the no-dot-terragrunt-cache experiment.

terragrunt.hcl
terraform {
no_dot_terragrunt_cache = true
}
update_source_with_casoptional(bool, false)

Lets a catalog’s terragrunt.hcl give source as a path relative to the catalog. Terragrunt rewrites it to a reference into its content-addressable store. See CAS integration.

units/service/terragrunt.hcl
terraform {
source = "../..//modules/service"
update_source_with_cas = true
}
mutableoptional(bool, false)

Makes the files Terragrunt copies from its content-addressable store into .terragrunt-cache writable. Terragrunt writes them read-only by default, so an edit can’t reach the shared store. It has no effect when Terragrunt fetches the source without the store, which already writes a separate, writable copy.

terragrunt.hcl
terraform {
source = "git::https://github.com/acme/modules.git//vpc?ref=v1.0.0"
mutable = true
}

Blocks

extra_argumentsextra_arguments "<name>" { … }

Passes extra CLI arguments, variable files, or environment variables to tofu/terraform for the commands you list. See Extra arguments.

namelabel

Names the set of arguments.

commandslist(string)

The tofu/terraform commands to pass the arguments to, e.g. ["apply", "plan"].

argumentsoptional(list(string))

CLI arguments to pass.

env_varsoptional(map(string))

Environment variables to set when Terragrunt calls tofu/terraform.

required_var_filesoptional(list(string))

Paths to .tfvars files, each passed as -var-file=<path>.

optional_var_filesoptional(list(string))

Like required_var_files, but Terragrunt skips a file that doesn’t exist.

terragrunt.hcl
terraform {
extra_arguments "retry_lock" {
commands = get_terraform_commands_that_need_locking()
arguments = ["-lock-timeout=20m"]
}
extra_arguments "common_vars" {
commands = ["apply", "plan", "import", "refresh"]
required_var_files = ["${get_parent_terragrunt_dir()}/common.tfvars"]
}
}
before_hookbefore_hook "<name>" { … }

Runs a command before tofu/terraform runs one of the commands you list. Hooks run in the order you declare them. See Hooks.

namelabel

Names the hook in Terragrunt’s log output.

commandslist(string)

The tofu/terraform commands to run the hook before. It also takes the hook commands init-from-module and init.

executelist(string)

The command to run and its arguments, e.g. ["echo", "Foo"] runs echo Foo.

working_diroptional(string)

The directory to run the command in. Defaults to the directory Terragrunt runs OpenTofu/Terraform in, or the unit’s directory for an init-from-module hook.

run_on_erroroptional(bool, false)

Runs the hook even when an earlier hook failed.

suppress_stdoutoptional(bool, false)

Hides the command’s standard output, e.g. when a script parses OpenTofu/Terraform’s output.

ifoptional(bool, true)

Skips the hook when false.

terragrunt.hcl
terraform {
before_hook "fmt" {
commands = ["apply", "plan"]
execute = ["tofu", "fmt", "-check"]
}
}
after_hookafter_hook "<name>" { … }

Runs a command after tofu/terraform runs one of the commands you list. Hooks run in the order you declare them. See Hooks.

namelabel

Names the hook in Terragrunt’s log output.

commandslist(string)

The tofu/terraform commands to run the hook after. It also takes the hook commands terragrunt-read-config, init-from-module, and init.

executelist(string)

The command to run and its arguments, e.g. ["echo", "Foo"] runs echo Foo.

working_diroptional(string)

The directory to run the command in. Defaults to the directory Terragrunt runs OpenTofu/Terraform in, or the unit’s directory for a terragrunt-read-config or init-from-module hook.

run_on_erroroptional(bool, false)

Runs the hook even when an earlier hook or the tofu/terraform command failed.

suppress_stdoutoptional(bool, false)

Hides the command’s standard output, e.g. when a script parses OpenTofu/Terraform’s output.

ifoptional(bool, true)

Skips the hook when false.

terragrunt.hcl
terraform {
after_hook "notify" {
commands = ["apply"]
execute = ["./scripts/notify.sh"]
run_on_error = true
}
}
error_hookerror_hook "<name>" { … }

Runs a command when tofu/terraform fails with an error that matches one of on_errors. Error hooks run after the before and after hooks.

namelabel

Names the hook in Terragrunt’s log output.

commandslist(string)

The tofu/terraform commands whose errors trigger the hook. Use init-from-module to catch errors while Terragrunt downloads source.

executelist(string)

The command to run and its arguments.

on_errorslist(string)

Regular expressions matched against the error message, e.g. [".*"] for any error.

working_diroptional(string)

The directory to run the command in. Defaults to the directory Terragrunt runs OpenTofu/Terraform in.

suppress_stdoutoptional(bool, false)

Hides the command’s standard output.

terragrunt.hcl
terraform {
error_hook "download_failed" {
commands = ["init-from-module"]
execute = ["echo", "Source download failed"]
on_errors = [".*"]
}
}