AWS Builder Center

Build a Production-Ready AWS VPC with Terraform

Learn how to provision a reusable AWS VPC using Terraform, including public and private subnets, an Internet Gateway, route tables, and security groups. This beginner-friendly guide explains the essential components, deployment commands, and cleanup steps.

Devops Engineer at Jio Platforms Ltd

Build a Production-Ready AWS VPC with Terraform

Infrastructure as Code (IaC) lets you create, update, and manage cloud infrastructure through version-controlled configuration files. Terraform is one of the most widely used IaC tools because it supports AWS and many other providers.
In this article, you will create a basic AWS VPC environment using Terraform. The architecture includes:
  • A VPC
  • One public subnet
  • One private subnet
  • An Internet Gateway
  • Route tables and route table associations
  • A security group for web traffic
Note: Always run terraform destroy after testing if you do not need the infrastructure anymore. This helps avoid unnecessary AWS charges.

Prerequisites

Before starting, make sure you have:
  • An AWS account
  • AWS CLI installed and configured
  • Terraform installed
  • Basic knowledge of AWS networking
  • An IAM user or role with permissions to create VPC resources
Verify your installations:
1
2
aws --version
terraform --version

Project structure

Create a new folder for the project:
1
2
mkdir terraform-aws-vpc
cd terraform-aws-vpc
Create these files:
1
2
3
4
terraform-aws-vpc/
├── main.tf
├── variables.tf
└── outputs.tf

Configure the AWS provider

Add the following to main.tf:
1
2
3
4
5
6
7
8
9
10
11
12
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = var.aws_region
}

Define variables

Create variables.tf:
1
2
3
4
5
6
7
8
9
10
11
variable "aws_region" {
description = "AWS Region for resources"
type = string
default = "ap-south-1"
}

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

Create the VPC

Add this to main.tf:
1
2
3
4
5
6
7
8
9
10
11
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true

tags = {
Name = "terraform-demo-vpc"
Environment = "dev"
ManagedBy = "Terraform"
}
}
This creates an isolated network with the CIDR range 10.0.0.0/16.

Create public and private subnets

Add the following resources:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-south-1a"
map_public_ip_on_launch = true

tags = {
Name = "public-subnet"
}
}

resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "ap-south-1b"

tags = {
Name = "private-subnet"
}
}
A public subnet can host resources that need direct internet access, such as an Application Load Balancer or a bastion host. A private subnet is suitable for application servers, databases, and internal services.

Add an Internet Gateway

An Internet Gateway enables communication between your VPC and the internet.
1
2
3
4
5
6
7
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id

tags = {
Name = "terraform-demo-igw"
}
}

Configure a public route table

Create a route table that sends internet-bound traffic through the Internet Gateway:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id

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

tags = {
Name = "public-route-table"
}
}

resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}

Create a security group

This example security group allows HTTP traffic from the internet. In production, restrict access based on your actual requirements.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
resource "aws_security_group" "web" {
name = "web-security-group"
description = "Allow HTTP inbound traffic"
vpc_id = aws_vpc.main.id

ingress {
description = "HTTP from the internet"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
description = "Allow all outbound traffic"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

tags = {
Name = "web-security-group"
}
}

Add outputs

Create outputs.tf:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
output "vpc_id" {
value = aws_vpc.main.id
}

output "public_subnet_id" {
value = aws_subnet.public.id
}

output "private_subnet_id" {
value = aws_subnet.private.id
}

output "web_security_group_id" {
value = aws_security_group.web.id
}

Deploy the infrastructure

Initialize Terraform:
1
terraform init
Review the resources Terraform plans to create:
1
terraform plan
Apply the configuration:
1
terraform apply
Type yes when Terraform asks for confirmation.
After deployment, Terraform will display the VPC, subnet, and security group IDs.

Verify resources in AWS

Open the AWS Management Console and check:
  • VPC dashboard for the new VPC
  • Subnets section for public and private subnets
  • Internet Gateways for the attached gateway
  • Route Tables for the public route
  • Security Groups for the HTTP rule

Clean up resources

When you finish testing, remove all resources created by Terraform:
1
terraform destroy
Review the deletion plan and type yes to confirm.

Conclusion

You have created a foundational AWS network using Terraform. This VPC design can be extended by adding:
  • NAT Gateway for private subnet internet access
  • EC2 instances or ECS services
  • Application Load Balancer
  • Amazon RDS in private subnets
  • AWS WAF for application protection
  • CloudWatch logging and monitoring
  • CI/CD workflows using GitHub Actions or GitLab CI
Using Terraform makes infrastructure repeatable, reviewable, and easier to manage as your AWS environment grows.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article