Terraform Tutorial — Module Structure
A Terraform module is simply a directory containing .tf files. The standard structure makes modules predictable and easy to understand.
Standard Module Layout
modules/vpc/
├── main.tf ← Resources
├── variables.tf ← Input variables
├── outputs.tf ← Output values
├── versions.tf ← Provider/Terraform version constraints
└── README.md ← Documentation
main.tf — Resources
# modules/vpc/main.tf
resource "aws_vpc" "this" {
cidr_block = var.cidr_block
enable_dns_hostnames = var.enable_dns_hostnames
enable_dns_support = true
tags = merge(var.tags, {
Name = "${var.name}-vpc"
})
}
resource "aws_subnet" "public" {
count = length(var.public_subnets)
vpc_id = aws_vpc.this.id
cidr_block = var.public_subnets[count.index]
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = merge(var.tags, {
Name = "${var.name}-public-${count.index + 1}"
})
}
variables.tf — Inputs
# modules/vpc/variables.tf
variable "name" {
type = string
description = "Name prefix for all resources"
}
variable "cidr_block" {
type = string
default = "10.0.0.0/16"
description = "CIDR block for the VPC"
}
variable "public_subnets" {
type = list(string)
default = ["10.0.1.0/24", "10.0.2.0/24"]
description = "List of public subnet CIDR blocks"
}
variable "availability_zones" {
type = list(string)
description = "List of availability zones"
}
variable "enable_dns_hostnames" {
type = bool
default = true
}
variable "tags" {
type = map(string)
default = {}
}
outputs.tf — Outputs
# modules/vpc/outputs.tf
output "vpc_id" {
value = aws_vpc.this.id
description = "The ID of the VPC"
}
output "public_subnet_ids" {
value = aws_subnet.public[*].id
description = "List of public subnet IDs"
}
output "vpc_cidr" {
value = aws_vpc.this.cidr_block
description = "CIDR block of the VPC"
}
versions.tf — Constraints
# modules/vpc/versions.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}
What’s Next?
You know the structure. Let’s learn how to call a module from your root configuration.