Terraform modules are very effective in structuring and managing infrastructure as code, enabling reusability, consistency, and scalability across projects. In this FAQ, we continue the discussion started in the Part 1 and cover the most common questions about versioning of Terraform modules, troubleshooting, and best practices.
Using Repositories to Store Terraform Modules:
Using External and Community Modules:
Common Pitfalls and Troubleshooting Terraform Modules
It is a best practice to store Terraform configurations and modules in version-controlled repositories. This enables teams to track changes, roll back to previous versions if needed, and manage infrastructure in a predictable, consistent manner.
There are two main options for storing and sharing modules: locally stored modules and modules in external registries.
Locally stored modules reside in a local directory within the project structure. Such approach is commonly used during development or for tightly coupled configurations.
Example usage:
Pros:
Cons:
Modules in external registries, as the name suggests, are hosted in central Git-like repositories or Terraform module registry (public or private).
Example with GitHub repository:
Where //mirror
indicates the location of the module within the repository and
ref=v1.0
references the required version or revision of the module.
Example with Terraform Registry:
Modules on the public Terraform Registry can be referenced using a registry source address of the form
<NAMESPACE>/<NAME>/<PROVIDER>
. Refer to the module's information page for the
exact address to use.
When using modules from a module registry, pin exact versions (version = "11.0.0"
) or use version
constraints (version = "~> 11.0"
) to avoid breaking changes.
Pros:
Cons:
In summary:
Use locally stored modules during initial development or for small, self-contained use cases.
For production, collaboration, and reusability, opt for external registries or Git-based modules with
proper versioning and documentation.
For more details see Terraform - Module Sources
Yes, Terraform supports retrieving modules from remote sources such as Amazon S3 buckets,
Google Cloud Storage (GCS) buckets, or even directly from HTTP(S) URLs. In these cases, the module
is packaged as a .zip
, .bz2
, or .gz
archive, commonly referred to as a
Terraform module package.
A Terraform package is a compressed archive of a module directory that can be fetched from a remote location
and used as a module source. This package must contain a valid Terraform module directory structure (e.g.,
main.tf
, variables.tf
, outputs.tf
, etc.), and it is extracted during the
terraform init
process.
Example with a S3 bucket:
Example with a GCS bucket:
Example with a web server (HTTP):
If the module is located in a subdirectory relative to the root of the package, add the module path to the URL,
preceded by a double slash (//
). For example: //modules/vpc
.
Terraform does not support version constraints for local modules. To manage versions manually, consider
using versioned directory structures - store different versions in separate folders
(../modules/vpc/v1.1
).
Example using a local module:
Then reference the specific version in the Terraform configuration:
External or third-party modules are best for common infrastructure patterns and rapid deployment.
Pros:
Cons:
Self-developed modules are better suited for custom workflows, internal tools, or organization-specific deployments.
Pros:
Cons:
Yes, there are some risks:
To mitigate these, always:
Some frequent mistakes when working with Terraform modules include:
Debugging issues in Terraform modules can involve a variety of tools and techniques. The most common problems include incorrect variable types, missing required inputs, dependency order issues, or syntax errors. Below are practical steps and tools to help troubleshoot these problems effectively:
Use terraform fmt
to check for syntax and formatting issues.
This command reformats your configuration files to follow Terraform's standard style. While it's primarily used for formatting, it also helps catch simple syntax errors (e.g., missing brackets, incorrect indentation) that could impact parsing.
Use terraform validate
to catch static errors.
This command performs a static analysis of the configuration to ensure it is syntactically valid and internally consistent, including:
Use terraform console
for interactive debugging.
This opens an interactive shell where you can inspect variables, expressions, and outputs. It's useful for understanding complex data structures, outputs, or expression evaluations.
Example:
Check module variable definitions and type constraints.
Ensure your module's variables.tf
file declares the correct types, and that consuming configurations
provide matching values.
Check resource dependencies and ordering.
Use depends_on
when Terraform can't automatically infer dependencies - especially for modules or resources
that reference outputs from others.
Expose module variables via outputs for debugging.
If you want to inspect or debug a module’s variable in the console, expose it using an output
in that module:
Example:
Simplify or isolate the module to narrow down the issue.
Sometimes testing with a minimal set of inputs helps identify the root cause.
Terraform logging can be enabled by setting the TF_LOG
environment variable to a desired level:
Levels include: TRACE
, DEBUG
, INFO
, WARN
, and ERROR
.
TRACE
provides the highest level of logging. Setting TF_LOG
to JSON
outputs
logs at the TRACE
level or higher, and uses a parsable JSON encoding as the formatting.
To disable logging, either unset TF_LOG
, or set it to off
.
You can also generate provider logs by setting the TF_LOG_PROVIDER
environment variable.
Use TF_LOG_PATH
to redirect logs to a file:
Verbose logs can help diagnose issues like variable resolution, provider behavior, and module initialization.
Upgrading a module can introduce breaking changes if:
To safely upgrade:
terraform plan
to preview changes before applying them.
Understanding how to effectively use, debug, and manage Terraform modules is key to building scalable and
maintainable infrastructure as code. By following best practices, leveraging tools like Terraform console,
validate
, and fmt
, and being mindful of common pitfalls, you can reduce errors and
improve collaboration across teams.
See Also:
Handling Terraform State in Multi-Environment Deployments
Understanding Terraform Variable Precedence
Terraform Value Types Tutorial
Terraform count
Explained with Practical Examples
Terraform for_each
Tutorial with Practical Examples
Exploring Terraform dynamic
Blocks with GCP Examples
Working with External Data in Terraform
Handling Sensitive and Ephemeral Data in Terraform