Terraform Tutorial — Project 4: Module Refactor
Refactor the VPC from Project 3 into a reusable module, then call it from multiple environments.
What You’ll Build
- Extract the VPC resources into
modules/vpc/ - Define clean inputs (variables) and outputs
- Call the module from a root configuration
- Demonstrate reusability with different parameters
Module Structure
project-4-modules/
├── modules/
│ └── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── main.tf
├── variables.tf
└── outputs.tf
modules/vpc/variables.tf
variable "name" {
type = string
description = "Name prefix for all VPC resources"
}
variable "cidr_block" {
type = string
default = "10.0.0.0/16"
}
variable "public_subnet_count" {
type = number
default = 2
}
variable "private_subnet_count" {
type = number
default = 2
}
variable "enable_nat_gateway" {
type = bool
default = true
}
variable "tags" {
type = map(string)
default = {}
}
modules/vpc/outputs.tf
output "vpc_id" {
value = aws_vpc.this.id
}
output "public_subnet_ids" {
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
value = aws_subnet.private[*].id
}
Root main.tf — Calling the Module
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
module "vpc" {
source = "./modules/vpc"
name = var.project_name
cidr_block = var.vpc_cidr
public_subnet_count = 2
private_subnet_count = 2
enable_nat_gateway = var.enable_nat
tags = {
Environment = var.environment
Project = var.project_name
}
}
Root outputs.tf
output "vpc_id" {
value = module.vpc.vpc_id
}
output "public_subnets" {
value = module.vpc.public_subnet_ids
}
output "private_subnets" {
value = module.vpc.private_subnet_ids
}
Reuse with Different Parameters
# Dev VPC — small, no NAT
module "vpc_dev" {
source = "./modules/vpc"
name = "dev"
cidr_block = "10.0.0.0/16"
enable_nat_gateway = false
}
# Prod VPC — larger, with NAT
module "vpc_prod" {
source = "./modules/vpc"
name = "prod"
cidr_block = "10.1.0.0/16"
public_subnet_count = 3
private_subnet_count = 3
enable_nat_gateway = true
}