Terraform modules are reusable, self-contained units of infrastructure-as-code: a bundle of resources, inputs, and outputs that turns a repeated pattern like a VPC or a compute cluster into something you write once and call from every environment. Well-designed modules are what let a team move from copy-pasted .tf files scattered across projects to a small, versioned catalog of building blocks that everyone trusts and composes together. The real leverage comes from treating a module like a public API: strict about what it accepts as input, deliberate about what it exposes as output, and versioned so consumers upgrade on their own schedule instead of being broken by someone else's change. Registries, whether HashiCorp's public one or a private/self-hosted equivalent, exist to make that versioning and discovery frictionless, but the registry only pays off if the module underneath follows the standard structure, pins its dependencies sensibly, and documents itself. This sheet covers how to structure, source, version, design, compose, publish, and refactor toward that kind of module.
What This Cheat Sheet Covers
This topic spans 13 focused tables and 99 indexed concepts. Below is a complete table-by-table outline of this topic, spanning foundational concepts through advanced details.
A jump-to index of every table row in this cheat sheet.
An interactive map of every table and concept in this topic.
Table 1: Standard Module Structure & Directory Layout
Every reusable module HashiCorp tooling can index and document follows the same predictable file layout, and only one piece of it is actually required.
| Element | Example | Description |
|---|---|---|
main.tfvariables.tfoutputs.tf | The only required piece of the standard module structure; Terraform files must live at the repository root and act as the module's primary entrypoint. | |
variable "instance_type" { type = string} | Recommended file for declaring every input variable block, even if the module currently has none. | |
output "instance_id" { value = aws_instance.web.id} | Recommended file for declaring every output block a module exposes. | |
README.md | Describes the module's purpose and usage; inputs/outputs don't need manual documentation because tooling generates them automatically. | |
LICENSE | Recommended for every module, especially public ones — many organizations won't adopt a module that lacks one. |