In this article, we will explain what module, root, and CWD Terraform file paths are, and how you can reference the different types of file paths, along with some reference examples.
TL;DR
Terraform path values help you locate files reliably. Use path.module inside modules, path.root for root config paths, and treat path.cwd only when you really mean the current working directory (it can change with -chdir and automation).
What are Terraform file paths?
File paths in Terraform allow you to reference paths that include various files and modules within your configuration. These configuration files typically have a .tf extension and contain the Terraform code necessary to describe and provision infrastructure resources. Terraform exposes a set of built-in path values you can use in your configuration: path.module, path.root, and path.cwd.
Types of path references in Terraform
The following types of path references (path.<TYPE>) are available in Terraform:
path.modulepath.rootpath.cwd
path.module is the path of the module where the expression is written, path.root is the path of the root Terraform module, and path.cwd is the shell’s current working directory when Terraform was run. In practice, path.module is usually the safest choice inside reusable modules, while path.cwd is the least portable.
| Value | What it points to | Changes by module location | Changes by where you run Terraform | Common use case | Caution |
path.module |
Directory of the current module | Yes | No | Referencing files packaged with that module | Best for reusable modules |
path.root |
Directory of the root module | No | No | Referencing files from the main stack/root config | Inside child modules, this still points to the root |
path.cwd |
Current working directory of the Terraform process | No | Yes | Rare edge cases, wrapper scripts, local execution context | Can break in CI/CD, automation, or when run from another directory |
Root Module Path
The root module is the main directory where your Terraform configuration files (.tf files) are located. The root module path is the absolute or relative path to the directory containing your main Terraform configuration. In most cases, the root module path is set to the directory where you run the terraform command.
Current Working Directory (CWD)
The current working directory is the directory from which the Terraform command is executed. Note that it can be different from the root module path if you run Terraform commands from a subdirectory.
Module Paths
Modules are self-contained packages of Terraform configurations. The path to a module is the directory where the module’s Terraform files are located. Module paths can be specified as relative or absolute paths.
Path Module
Terraform provides a path module that you can use to work with file paths within your Terraform code. The path module includes functions path.cwd, path.root and path.module to retrieve the current working directory, root module path, and filesystem path of the module where the expression is placed respectively.
What is the difference between path root and path module?
path.root and path.module are functions provided by the path module to retrieve information about file paths within your Terraform configuration. The key difference is that path.root always refers to the root module’s directory, while path.module dynamically reflects the directory containing the module’s configuration files. Using these functions can be helpful when you need to generate file paths dynamically or when dealing with modularized Terraform projects.
Path.module example
Adding the below output block to your configuration, if run within a module, it will output the path to that module’s directory when you execute terraform apply.
output "module_path" {
value = path.module
}It is not recommend to use
path.modulein write operations because it can produce different behavior depending on whether you use remote or local module sources. Multiple invocations of local modules use the same source directory, overwriting the data inpath.moduleduring each call. This can lead to race conditions and unexpected results.
To further explain the value the path.module function will produce, consider the following file and directory structure:
my_terraform_project/
|-- main.tf
|-- variables.tf
|-- outputs.tf
|-- modules/
| |-- web_server/
| |-- main.tf
| |-- variables.tf
| |-- outputs.tfThe contents of the my_terraform_project/modules/web_server/outputs.tf file looks like this:
output "module_path" {
value = path.module
} When terraform apply is run in the root directory, you’ll see output similar to the following:
Outputs:
module_path = /path/to/my_terraform_project/modules/web_serverPath.root example
If you run this in a file within a subdirectory of your Terraform project, it will output the path to the root directory when you execute terraform apply.
output "root_path" {
value = path.root
}Consider the same file structure shown in the previous example. The output.tf file in the root directory (my_terraform_project/outputs.tf) includes the above code. The output would be similar to the below when terraform apply is run.
Outputs:
root_module_path = /path/to/my_terraform_projectPath.cwd example
If you run this in a file within a subdirectory of your Terraform project, it will output the path to the current working directory before applying any -chdir arguments when you execute terraform apply.
It should be used with caution, e.g., if used to directly populate a path into a resource argument, then later applying the same configuration from a different directory or on a different computer with a different directory structure will cause the provider to consider the change of path to be a change to be applied, even if the path still refers to the same file.
output "cwd" {
value = path.cwd
}This path is an absolute path that includes details about the filesystem structure. It is also useful in some advanced cases where Terraform is run from a directory other than the root module directory. It is recommend to use
path.rootorpath.moduleoverpath.cwdwhere possible.
Again, using the example file structure from the previous examples, consider the output.tf file in the root directory (my_terraform_project/outputs.tf) includes the above code. The output would be similar to the below when terraform apply is run.
Outputs:
current_working_directory = /path/to/my_terraform_projectBest practices when using Terraform paths
Best practices when using path.module, path.root, and path.cwd include:
- Prefer path.module inside reusable modules to keep file references self-contained and portable.
- Use path.root only for true “root-level” concerns (shared config, envs/ folders, etc.).
- Treat path.cwd as an advanced feature – it depends on where Terraform/OpenTofu is run, so avoid it in reusable modules.
- It’s safe and common to read files using these paths (templates, policies, YAML/JSON configs).
- Avoid writing files into path.module or path.root from provisioners or scripts, to prevent race conditions and non-reproducible plans.
- Don’t bake paths into resource names or other stable identifiers – moving the code would force unnecessary recreations.
- Always test your path usage in automation/CI (e.g. Spacelift), not just locally, to catch differences in working directory or -chdir behavior.
Key points
Terraform provides a path module that you can use to work with file paths within your Terraform code. Choosing which function you use to reference paths should be understood carefully to avoid any unintended consequences when running your code on different systems with different directory structures.
We encourage you also to explore how Spacelift makes it easy to work with Terraform. If you need any help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this. It supports Git workflows, policy as code, programmatic configuration, context sharing, drift detection, and many more great features right out of the box. You can check it for free, by creating a trial account or booking a demo.
Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.
Manage Terraform Better with Spacelift
Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization, and many more.
Frequently asked questions
What’s the difference between path.module, path.root, and path.cwd in Terraform file paths?
In Terraform,
path.module,path.root, andpath.cwdrefer to different directory contexts during execution, affecting how file paths are resolved:path.modulereturns the filesystem path of the current module where the expression is usedpath.rootreturns the root module’s path, which is where Terraform was initially runpath.cwdreturns the current working directory of the Terraform process, which can differ if the CLI is run from a subdirectory
Is path.module an absolute path or a relative path?
path.module is an absolute filesystem path.
Does path.root change inside child modules?
path.root always points to the root module directory, even when referenced from inside a child module.
Why is using path.cwd risky in CI or remote runs?
In remote/ephemeral runners, path.cwd can resolve to environment-specific absolute paths and become unreliable. Using path.root or path.module is typically more stable/portable.
Do OpenTofu and Terraform behave the same for these path values?
In practice, path values in Terraform and OpenTofu are treated as the same named values in most workflows, but if you’re documenting this explicitly, it’s worth adding a one-liner noting behavior is expected to match and linking to the relevant OpenTofu docs if you have a canonical reference.
