Terraform VPC Creator
Use Case: Scaffold a complete AWS VPC module in HCL with subnets, IGW, NAT gateway, and route tables
System Instructions
You are a Terraform and AWS networking expert. Generate production-grade HCL modules with correct resource dependencies, tagging, and remote state compatibility. User Prompt Template
Generate a Terraform AWS VPC module:
Project: {PROJECT_NAME}
CIDR: {VPC_CIDR}
AZs: {AVAILABILITY_ZONES}
NAT gateway: {NAT_STRATEGY}
Environment: {ENVIRONMENT} Run This Prompt โ SDK Snippets
Implementation Guidelines
What This Prompt Does
This prompt scaffolds a complete, production-ready Terraform AWS VPC module from a minimal set of inputs. The output includes the VPC, public and private subnets across multiple availability zones, an Internet Gateway, NAT Gateways (with cost-optimized single-AZ or HA per-AZ options), route tables, and all necessary associations. The module is structured for reuse across environments (dev, staging, prod) via variable files.
System Prompt
You are a Terraform and AWS networking expert with deep experience in multi-account,
multi-region AWS architectures and Infrastructure-as-Code best practices.
When generating Terraform HCL:
1. Structure output as a reusable module: main.tf, variables.tf, outputs.tf โ separated
by "# === filename ===" comments.
2. Use terraform >= 1.5 and aws provider >= 5.0 syntax.
3. Use for_each or count for resources that repeat across AZs โ never copy-paste blocks.
4. Every resource must have a "tags" block that merges module-level tags with resource-specific tags.
5. Use depends_on only when implicit dependencies cannot be inferred (rare โ explain why).
6. Outputs must export: vpc_id, public_subnet_ids, private_subnet_ids, nat_gateway_ids.
7. NAT strategy:
- "single": one NAT GW in the first public subnet (cost-optimized for dev)
- "per_az": one NAT GW per AZ (HA for production)
8. Add inline comments explaining CIDR math and design decisions.
9. Do NOT use deprecated aws_subnet data sources or legacy aws_internet_gateway attachment syntax.
User Prompt Template
Generate a complete Terraform AWS VPC module.
Project name: {PROJECT_NAME}
VPC CIDR block: {VPC_CIDR} (e.g., "10.0.0.0/16")
Availability zones: {AVAILABILITY_ZONES} (e.g., ["us-east-1a", "us-east-1b", "us-east-1c"])
NAT gateway strategy: {NAT_STRATEGY} ("single" or "per_az")
Environment: {ENVIRONMENT} (e.g., "production")
Additional requirements: {SPECIAL_REQUIREMENTS} (e.g., "enable VPC Flow Logs to CloudWatch", "add VPC endpoints for S3 and DynamoDB")
Output main.tf, variables.tf, and outputs.tf.
Example Output
Model output (abridged for readability):
# === variables.tf ===
variable "project_name" {
description = "Name of the project, used in all resource tags and names."
type = string
}
variable "vpc_cidr" {
description = "CIDR block for the VPC (e.g., 10.0.0.0/16)."
type = string
default = "10.0.0.0/16"
}
variable "availability_zones" {
description = "List of AZs to deploy subnets into."
type = list(string)
}
variable "nat_strategy" {
description = "NAT gateway strategy: 'single' (cost-optimized) or 'per_az' (HA)."
type = string
default = "single"
validation {
condition = contains(["single", "per_az"], var.nat_strategy)
error_message = "nat_strategy must be 'single' or 'per_az'."
}
}
variable "environment" {
description = "Deployment environment (dev, staging, production)."
type = string
}
# === main.tf ===
locals {
# Divide the VPC CIDR into /24 subnets for simplicity.
# Public subnets: 10.x.0.0/24, 10.x.1.0/24, ...
# Private subnets: 10.x.10.0/24, 10.x.11.0/24, ...
public_cidr_blocks = [for i, az in var.availability_zones : cidrsubnet(var.vpc_cidr, 8, i)]
private_cidr_blocks = [for i, az in var.availability_zones : cidrsubnet(var.vpc_cidr, 8, i + 10)]
common_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
}
}
resource "aws_vpc" "this" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = merge(local.common_tags, { Name = "${var.project_name}-vpc" })
}
resource "aws_internet_gateway" "this" {
vpc_id = aws_vpc.this.id
tags = merge(local.common_tags, { Name = "${var.project_name}-igw" })
}
resource "aws_subnet" "public" {
for_each = { for i, az in var.availability_zones : az => i }
vpc_id = aws_vpc.this.id
cidr_block = local.public_cidr_blocks[each.value]
availability_zone = each.key
map_public_ip_on_launch = true
tags = merge(local.common_tags, {
Name = "${var.project_name}-public-${each.key}"
Tier = "public"
})
}
resource "aws_subnet" "private" {
for_each = { for i, az in var.availability_zones : az => i }
vpc_id = aws_vpc.this.id
cidr_block = local.private_cidr_blocks[each.value]
availability_zone = each.key
tags = merge(local.common_tags, {
Name = "${var.project_name}-private-${each.key}"
Tier = "private"
})
}
resource "aws_eip" "nat" {
# Create one EIP per NAT GW. In "single" mode, only 1 EIP is needed.
for_each = var.nat_strategy == "per_az" ? aws_subnet.public : { (keys(aws_subnet.public)[0]) = aws_subnet.public[keys(aws_subnet.public)[0]] }
domain = "vpc"
tags = merge(local.common_tags, { Name = "${var.project_name}-nat-eip-${each.key}" })
}
resource "aws_nat_gateway" "this" {
for_each = aws_eip.nat
allocation_id = aws_eip.nat[each.key].id
subnet_id = aws_subnet.public[each.key].id
tags = merge(local.common_tags, { Name = "${var.project_name}-nat-${each.key}" })
depends_on = [aws_internet_gateway.this]
}
# ... route tables and associations omitted for brevity
# === outputs.tf ===
output "vpc_id" {
description = "The ID of the created VPC."
value = aws_vpc.this.id
}
output "public_subnet_ids" {
description = "List of public subnet IDs."
value = [for s in aws_subnet.public : s.id]
}
output "private_subnet_ids" {
description = "List of private subnet IDs."
value = [for s in aws_subnet.private : s.id]
}
Tips & Variations
- Remote state configuration: Ask for
"Also generate a backend.tf with S3 remote state and DynamoDB locking"as part of{SPECIAL_REQUIREMENTS}. The model will produce the correctterraform { backend "s3" { ... } }block. - VPC Endpoints for cost savings: Add
"Add S3 and DynamoDB gateway VPC endpoints to eliminate NAT costs for AWS service traffic"to requirements. At scale, this can reduce NAT gateway bills by 30โ70%. - Transit Gateway attachment: For multi-VPC architectures, include
"Add a Transit Gateway attachment resource and a route in private route tables pointing 10.0.0.0/8 to the TGW"to wire up hub-and-spoke networking. - Terragrunt wrapper: Ask the model to output a
terragrunt.hclalongside the module to handle remote state, AWS provider version pinning, and environment-specific variable injection automatically.