Terraform Tutorial — Project 4: Module Refactor

1 minute read

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
}

← Project 3: VPC Network Project 5: Multi-Environment →