Module Structure
Imagine you’re building a Lego set. If all the pieces are scattered randomly, it’s hard to reuse or share them. But if you package them neatly like bricks in one box, instructions in another then you can rebuild the set anytime and even share it with friends.
Terraform modules work the same way. A well‑structured module makes your infrastructure reusable, clear, and easy to maintain. In this chapter, you’ll learn the standard structure of a Terraform module and why it matters.
Standard Module Files
main.tf→ Core resources of the module.variables.tf→ Input variables that parameterize the module.outputs.tf→ Output values that expose useful information.README.md→ Documentation for usage and examples.
Optional Files
providers.tf→ Defines required providers and versions.versions.tf→ Specifies Terraform version constraints.locals.tf→ Stores local values for simplifying logic.examples/folder → Demonstrates how to use the module.
Example Module Structure
modules/
└── ec2/
├── main.tf
├── variables.tf
├── outputs.tf
├── providers.tf
├── versions.tf
├── README.md
└── examples/
└── basic_usage.tf
Why Structure Matters
- Clarity: Easy for others to understand and use.
- Reusability: Standardized inputs/outputs make modules portable.
- Maintainability: Centralized changes propagate across environments.
- Collaboration: Teams can share modules confidently.
Hands‑On Lab / Demo
Lab: Building a Structured EC2 Module
Use the module in root config:
module "web" {
source = "./modules/ec2"
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
instance_name = "web-server"
}
Create modules/ec2/outputs.tf:
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.example.id
}
output "public_ip" {
description = "Public IP of the EC2 instance"
value = aws_instance.example.public_ip
}
Create modules/ec2/variables.tf:
variable "ami" {
description = "AMI ID for the instance"
type = string
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.micro"
}
variable "instance_name" {
description = "Tag name for the instance"
type = string
}
Create modules/ec2/main.tf:
resource "aws_instance" "example" {
ami = var.ami
instance_type = var.instance_type
tags = {
Name = var.instance_name
}
}
Pro Tips & Best Practices
- Always include
README.mdwith usage examples. - Keep modules small and focused (single responsibility).
- Use semantic versioning for module releases.
- Document inputs/outputs clearly.
- Provide examples for quick adoption.
Summary & Cheatsheet
- Core files:
main.tf,variables.tf,outputs.tf. - Optional files:
providers.tf,versions.tf,locals.tf,README.md. - Structure benefits: clarity, reusability, maintainability, collaboration.
Quick mnemonic: Main, Variables, Outputs = Module Core
The Hackers Notebook
Module structure is the blueprint for reusability. By organizing files consistently, you make your modules easy to understand, adopt, and maintain. This sets the stage for building a library of reusable infrastructure components.
