Skip to main content

Overview

This example demonstrates the simplest VPC configuration with basic public and private subnets. It’s ideal for development environments or when you’re just getting started with AWS networking.
This basic configuration uses a single NAT Gateway shared across all availability zones to minimize costs. For production environments, consider using multiple NAT Gateways for high availability.

What Gets Created

1

VPC with DNS support

A VPC with CIDR block 10.0.0.0/16 and DNS hostnames enabled for internal name resolution.
2

Public subnets across 2 AZs

Two public subnets (10.0.1.0/24 and 10.0.2.0/24) with Internet Gateway access for resources that need public internet connectivity.
3

Private subnets across 2 AZs

Two private subnets (10.0.101.0/24 and 10.0.102.0/24) with NAT Gateway for outbound internet access while keeping resources private.
4

Single shared NAT Gateway

One NAT Gateway in the first availability zone, shared across all private subnets to reduce costs.

Complete Configuration

module "vpc" {
  source = "github.com/Planview/tf_aws_vpc"

  name = "dev-vpc"
  cidr = "10.0.0.0/16"

  # Availability zones
  azs = ["us-east-1a", "us-east-1b"]

  # Subnets
  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
  private_subnets = ["10.0.101.0/24", "10.0.102.0/24"]

  # Enable DNS
  enable_dns_hostnames = true
  enable_dns_support   = true

  # NAT Gateway - single shared gateway for cost savings
  enable_nat_gateway = true
  single_nat_gateway = true

  # Auto-assign public IPs in public subnets
  map_public_ip_on_launch = true

  # Tags
  tags = {
    Terraform   = "true"
    Environment = "development"
    Project     = "my-app"
  }
}

# Outputs to reference VPC resources in other configurations
output "vpc_id" {
  description = "The ID of the VPC"
  value       = module.vpc.vpc_id
}

output "public_subnets" {
  description = "List of IDs of public subnets"
  value       = module.vpc.public_subnets
}

output "private_subnets" {
  description = "List of IDs of private subnets"
  value       = module.vpc.private_subnets
}

output "nat_public_ips" {
  description = "Public IP address of NAT Gateway"
  value       = module.vpc.nat_eips_public_ips
}

output "default_security_group_id" {
  description = "Default security group ID"
  value       = module.vpc.default_security_group_id
}

Key Configuration Choices

Single NAT Gateway

This example uses single_nat_gateway = true to provision only one NAT Gateway. This reduces costs significantly but creates a single point of failure. If the availability zone hosting the NAT Gateway experiences an outage, private subnets in other AZs will lose internet connectivity.

CIDR Block Design

The /16 CIDR block provides 65,536 IP addresses, with public subnets in the 10.0.1.0/24 - 10.0.50.0/24 range and private subnets starting at 10.0.101.0/24. This leaves room for expansion.

DNS Configuration

Both enable_dns_hostnames and enable_dns_support are enabled to allow EC2 instances to resolve each other by DNS names within the VPC.

Using the Outputs

After applying this configuration, you can reference the VPC resources in other Terraform configurations:
# Example: Launch an EC2 instance in the VPC
resource "aws_instance" "app" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  subnet_id     = module.vpc.private_subnets[0]

  tags = {
    Name = "app-server"
  }
}

# Example: Create a load balancer in public subnets
resource "aws_lb" "main" {
  name               = "app-lb"
  internal           = false
  load_balancer_type = "application"
  subnets            = module.vpc.public_subnets

  tags = {
    Name = "app-load-balancer"
  }
}

Cost Considerations

This configuration will incur charges for:
  • 1 NAT Gateway (~$32/month + data processing)
  • 1 Elastic IP (~$3.60/month when not associated)
Total estimated cost: ~$35-40/month plus data transfer costs.

Build docs developers (and LLMs) love