INFRASTRUCTURE AS CODE

VPC Infrastructure with Terraform

Production-ready Virtual Private Cloud with multi-AZ deployment, public/private subnets, and NAT Gateway using Terraform.

TerraformVPCNAT GatewayMulti-AZRoute TablesSubnets

PROJECT OVERVIEW

OBJECTIVE

Design and deploy a production-grade VPC with proper network segmentation, high availability, and secure internet access for private resources.

APPROACH

Used Terraform to define infrastructure as code, enabling version control, repeatability, and automated deployment across multiple environments.

OUTCOME

Fully functional multi-AZ VPC with public and private subnets, NAT Gateway for outbound traffic, and modular Terraform configuration.

ARCHITECTURE DIAGRAM

VPC Architecture Diagram

NETWORK ARCHITECTURE

  • VPC with 10.0.0.0/16 CIDR block
  • 2 Public subnets across different AZs
  • 2 Private subnets for backend resources
  • Internet Gateway for public internet access

KEY FEATURES

  • NAT Gateway for private subnet internet access
  • Separate route tables for public/private subnets
  • Multi-AZ deployment for high availability
  • Optional VPC Flow Logs for monitoring

TERRAFORM CONFIGURATION

main.tf
# VPC Configuration
resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "${var.project_name}-vpc"
    Environment = var.environment
  }
}

# Internet Gateway
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "${var.project_name}-igw"
  }
}

# Public Subnets
resource "aws_subnet" "public" {
  count                   = length(var.public_subnet_cidrs)
  vpc_id                  = aws_vpc.main.id
  cidr_block              = var.public_subnet_cidrs[count.index]
  availability_zone       = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.project_name}-public-${count.index + 1}"
    Type = "Public"
  }
}

# Private Subnets
resource "aws_subnet" "private" {
  count             = length(var.private_subnet_cidrs)
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.private_subnet_cidrs[count.index]
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = {
    Name = "${var.project_name}-private-${count.index + 1}"
    Type = "Private"
  }
}

# Elastic IP for NAT Gateway
resource "aws_eip" "nat" {
  domain = "vpc"
  
  tags = {
    Name = "${var.project_name}-nat-eip"
  }
}

# NAT Gateway
resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public[0].id

  tags = {
    Name = "${var.project_name}-nat"
  }

  depends_on = [aws_internet_gateway.main]
}

# Public Route Table
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = {
    Name = "${var.project_name}-public-rt"
  }
}

# Private Route Table
resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main.id
  }

  tags = {
    Name = "${var.project_name}-private-rt"
  }
}

# Route Table Associations
resource "aws_route_table_association" "public" {
  count          = length(aws_subnet.public)
  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "private" {
  count          = length(aws_subnet.private)
  subnet_id      = aws_subnet.private[count.index].id
  route_table_id = aws_route_table.private.id
}
variables.tf
variable "project_name" {
  description = "Project name for resource naming"
  type        = string
  default     = "cloud-portfolio"
}

variable "environment" {
  description = "Environment (dev, staging, prod)"
  type        = string
  default     = "dev"
}

variable "vpc_cidr" {
  description = "CIDR block for VPC"
  type        = string
  default     = "10.0.0.0/16"
}

variable "public_subnet_cidrs" {
  description = "CIDR blocks for public subnets"
  type        = list(string)
  default     = ["10.0.1.0/24", "10.0.2.0/24"]
}

variable "private_subnet_cidrs" {
  description = "CIDR blocks for private subnets"
  type        = list(string)
  default     = ["10.0.3.0/24", "10.0.4.0/24"]
}

variable "enable_flow_logs" {
  description = "Enable VPC Flow Logs"
  type        = bool
  default     = false
}

DEPLOYMENT STEPS

01

Install Terraform

Download and install Terraform CLI (v1.0+)

02

Configure AWS Provider

Set up AWS credentials and provider configuration

03

Initialize Terraform

Run 'terraform init' to download providers

04

Plan Infrastructure

Execute 'terraform plan' to preview changes

05

Apply Configuration

Run 'terraform apply' to create resources

06

Verify Deployment

Check AWS Console for created VPC and subnets

KEY LEARNINGS

TECHNICAL SKILLS

  • • Infrastructure as Code with Terraform
  • • VPC design and network segmentation
  • • Multi-AZ architecture for high availability
  • • NAT Gateway configuration and routing
  • • Terraform state management and modules

BEST PRACTICES

  • • Use variables for reusable configurations
  • • Implement proper CIDR block planning
  • • Enable VPC Flow Logs for security monitoring
  • • Use remote state storage (S3 + DynamoDB)
  • • Tag all resources for cost allocation