✅ Task 2 — Create a Reusable VPC Module with Environments using Terraform (dev/stage/prod)

📘 Scenario

Your company wants to standardize the AWS network setup across all environments — dev, stage, and prod.

Architects want a Terraform VPC module that:

Creates a VPC with configurable CIDR
Creates customizable public and private s…


This content originally appeared on DEV Community and was authored by Latchu@DevOps

📘 Scenario

Your company wants to standardize the AWS network setup across all environments — dev, stage, and prod.

Architects want a Terraform VPC module that:

  • Creates a VPC with configurable CIDR
  • Creates customizable public and private subnets
  • Creates an Internet Gateway
  • Creates NAT Gateways (only for stage & prod)
  • Expose outputs so other teams can use the VPC module

Your task is to:

  1. Build a reusable Terraform VPC module
  2. Deploy the module for dev, stage, prod
  3. Make the module flexible using variables

🎯 What You Will Learn

  • How to write a Terraform module
  • How to structure multi-environment Terraform directories
  • How to use variables & outputs
  • How to control resources using count and conditional logic
  • How to avoid repeated code

📁 Final Directory Structure (Goal)

terraform-task-02/
├── envs
│   ├── dev
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── terraform.tfvars
│   ├── stage
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── terraform.tfvars
│   └── prod
│       ├── main.tf
│       ├── variables.tf
│       └── terraform.tfvars
└── modules
    └── vpc
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

🧩 Step 1: Create the VPC Module

modules/vpc/variables.tf

variable "vpc_cidr" {
  type = string
}

variable "public_subnets" {
  type = list(string)
}

variable "private_subnets" {
  type = list(string)
}

variable "enable_nat" {
  type    = bool
  default = false
}

variable "tags" {
  type    = map(string)
  default = {}
}

modules/vpc/main.tf

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = merge(var.tags, {
    Name = "main-vpc"
  })
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "igw"
  }
}

resource "aws_subnet" "public" {
  count                   = length(var.public_subnets)
  vpc_id                  = aws_vpc.main.id
  cidr_block              = var.public_subnets[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name = "public-${count.index}"
  }
}

resource "aws_subnet" "private" {
  count      = length(var.private_subnets)
  vpc_id     = aws_vpc.main.id
  cidr_block = var.private_subnets[count.index]

  tags = {
    Name = "private-${count.index}"
  }
}

# NAT only if enabled
resource "aws_eip" "nat" {
  count = var.enable_nat ? 1 : 0
}

resource "aws_nat_gateway" "nat" {
  count         = var.enable_nat ? 1 : 0
  subnet_id     = aws_subnet.public[0].id
  allocation_id = aws_eip.nat[0].id
}

modules/vpc/outputs.tf

output "vpc_id" {
  value = aws_vpc.main.id
}

output "public_subnets" {
  value = aws_subnet.public[*].id
}

output "private_subnets" {
  value = aws_subnet.private[*].id
}

output "nat_gateway_id" {
  value = var.enable_nat ? aws_nat_gateway.nat[0].id : null
}

🧩 Step 2: Create Environment Configurations

🔹 envs/dev/variables.tf

variable "vpc_cidr" {}
variable "public_subnets" {}
variable "private_subnets" {}
variable "enable_nat" {}

🔹 envs/dev/main.tf

provider "aws" {
  region = "us-east-1"
}

module "vpc" {
  source = "../../modules/vpc"

  vpc_cidr        = var.vpc_cidr
  public_subnets  = var.public_subnets
  private_subnets = var.private_subnets
  enable_nat      = var.enable_nat

  tags = {
    Environment = "dev"
  }
}

🔹 envs/dev/terraform.tfvars

vpc_cidr = "10.0.0.0/16"

public_subnets = [
  "10.0.1.0/24",
  "10.0.2.0/24"
]

private_subnets = [
  "10.0.11.0/24",
  "10.0.12.0/24"
]

enable_nat = false

Same as dev, except NAT enabled:

🔹 envs/stage/variables.tf

variable "vpc_cidr" {}
variable "public_subnets" {}
variable "private_subnets" {}
variable "enable_nat" {}

🔹 envs/stage/main.tf

provider "aws" {
  region = "us-east-1"
}

module "vpc" {
  source = "../../modules/vpc"

  vpc_cidr        = var.vpc_cidr
  public_subnets  = var.public_subnets
  private_subnets = var.private_subnets
  enable_nat      = var.enable_nat

  tags = {
    Environment = "stage"
  }
}

🔹 envs/stage/terraform.tfvars

vpc_cidr = "10.1.0.0/16"

public_subnets = [
  "10.1.1.0/24",
  "10.1.2.0/24"
]

private_subnets = [
  "10.1.11.0/24",
  "10.1.12.0/24"
]

enable_nat = true

🔹 envs/prod/variables.tf

variable "vpc_cidr" {}
variable "public_subnets" {}
variable "private_subnets" {}
variable "enable_nat" {}

🔹 envs/prod/main.tf

provider "aws" {
  region = "us-east-1"
}

module "vpc" {
  source = "../../modules/vpc"

  vpc_cidr        = var.vpc_cidr
  public_subnets  = var.public_subnets
  private_subnets = var.private_subnets
  enable_nat      = var.enable_nat

  tags = {
    Environment = "prod"
  }
}

🔹 envs/prod/terraform.tfvars

vpc_cidr = "10.2.0.0/16"

public_subnets = [
  "10.2.1.0/24",
  "10.2.2.0/24"
]

private_subnets = [
  "10.2.11.0/24",
  "10.2.12.0/24"
]

enable_nat = true

1

🚀 Step 3: Deploy the VPC

Run dev environment

cd envs/dev
terraform init
terraform plan
terraform apply

Run stage

cd envs/stage
terraform init
terraform plan
terraform apply

Run prod

cd envs/prod
terraform init
terraform plan
terraform apply

🌟 Thanks for reading! If this post added value, a like ❤️, follow, or share would encourage me to keep creating more content.

— Latchu | Senior DevOps & Cloud Engineer

☁️ AWS | GCP | ☸️ Kubernetes | 🔐 Security | ⚡ Automation
📌 Sharing hands-on guides, best practices & real-world cloud solutions


This content originally appeared on DEV Community and was authored by Latchu@DevOps


Print Share Comment Cite Upload Translate Updates
APA

Latchu@DevOps | Sciencx (2025-11-15T10:41:52+00:00) ✅ Task 2 — Create a Reusable VPC Module with Environments using Terraform (dev/stage/prod). Retrieved from https://www.scien.cx/2025/11/15/%e2%9c%85-task-2-create-a-reusable-vpc-module-with-environments-using-terraform-dev-stage-prod/

MLA
" » ✅ Task 2 — Create a Reusable VPC Module with Environments using Terraform (dev/stage/prod)." Latchu@DevOps | Sciencx - Saturday November 15, 2025, https://www.scien.cx/2025/11/15/%e2%9c%85-task-2-create-a-reusable-vpc-module-with-environments-using-terraform-dev-stage-prod/
HARVARD
Latchu@DevOps | Sciencx Saturday November 15, 2025 » ✅ Task 2 — Create a Reusable VPC Module with Environments using Terraform (dev/stage/prod)., viewed ,<https://www.scien.cx/2025/11/15/%e2%9c%85-task-2-create-a-reusable-vpc-module-with-environments-using-terraform-dev-stage-prod/>
VANCOUVER
Latchu@DevOps | Sciencx - » ✅ Task 2 — Create a Reusable VPC Module with Environments using Terraform (dev/stage/prod). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/11/15/%e2%9c%85-task-2-create-a-reusable-vpc-module-with-environments-using-terraform-dev-stage-prod/
CHICAGO
" » ✅ Task 2 — Create a Reusable VPC Module with Environments using Terraform (dev/stage/prod)." Latchu@DevOps | Sciencx - Accessed . https://www.scien.cx/2025/11/15/%e2%9c%85-task-2-create-a-reusable-vpc-module-with-environments-using-terraform-dev-stage-prod/
IEEE
" » ✅ Task 2 — Create a Reusable VPC Module with Environments using Terraform (dev/stage/prod)." Latchu@DevOps | Sciencx [Online]. Available: https://www.scien.cx/2025/11/15/%e2%9c%85-task-2-create-a-reusable-vpc-module-with-environments-using-terraform-dev-stage-prod/. [Accessed: ]
rf:citation
» ✅ Task 2 — Create a Reusable VPC Module with Environments using Terraform (dev/stage/prod) | Latchu@DevOps | Sciencx | https://www.scien.cx/2025/11/15/%e2%9c%85-task-2-create-a-reusable-vpc-module-with-environments-using-terraform-dev-stage-prod/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.