Build a Custom VPC with Public & Private Subnets in AWS Using Terraform


If you’re diving into AWS networking or practicing Infrastructure as Code (IaC), setting up a custom VPC from scratch with Terraform is a great hands-on project. In this guide, we’ll walk through how to:
Create a VPC
Add public and private subnets
Attach an internet gateway
Configure a routing table
Launch an EC2 instance in the public subnet
Let’s get started! 🔧
Terraform Project Setup
1️⃣ Terraform Configuration
Start with your main.tf
file, which defines the required provider and sets the AWS region:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "6.0.0-beta2"
}
}
}
provider "aws" {
region = "us-east-2"
}
Create VPC and Subnets
2️⃣ Create a VPC
We’ll create a VPC with a /16
CIDR block:
resource "aws_vpc" "my-vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "my_vpc"
}
}
3️⃣ Define Subnets
- Private Subnet:
resource "aws_subnet" "private-subnet" {
cidr_block = "10.0.1.0/24"
vpc_id = aws_vpc.my-vpc.id
tags = {
Name = "private-subnet"
}
}
- Public Subnet:
resource "aws_subnet" "public-subnet" {
cidr_block = "10.0.2.0/24"
vpc_id = aws_vpc.my-vpc.id
tags = {
Name = "public-subnet"
}
}
Internet Access
4️⃣ Add Internet Gateway
We’ll need an internet gateway so instances in the public subnet can access the internet:
resource "aws_internet_gateway" "my-igw" {
vpc_id = aws_vpc.my-vpc.id
tags = {
Name = "my-igw"
}
}
5️⃣ Create Route Table & Associate
This route table allows public subnet traffic to route through the internet gateway:
resource "aws_route_table" "my-rt" {
vpc_id = aws_vpc.my-vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.my-igw.id
}
}
resource "aws_route_table_association" "public-sub" {
route_table_id = aws_route_table.my-rt.id
subnet_id = aws_subnet.public-subnet.id
}
💻 Launch EC2 Instance in Public Subnet
To verify the setup works, we’ll launch a simple EC2 instance in the public subnet.
resource "aws_instance" "server28" {
ami = "ami-06c8f2ec674c67112" # Amazon Linux 2 AMI (example)
instance_type = "t2.micro"
subnet_id = aws_subnet.public-subnet.id
tags = {
Name = "tfserver1"
}
}
Note: Ensure the AMI ID is valid for your selected region (
us-east-2
in this case). You can find the latest AMI IDs from the AWS Console or AMI Marketplace.
Terraform Commands in Action
Now that your infrastructure is defined, it’s time to run the Terraform workflow:
Project Directory Setup
Make sure you are in the correct working directory:
cd Terraform_vpc/aws-vpc
(Optional: If you’re using environment variables, source them first.)
source .env
1️⃣ Initialize Terraform
terraform init
This downloads the required provider plugins and sets up the backend.
2️⃣ Validate Your Code
terraform validate
Confirms that your configuration is syntactically correct.
3️⃣ Apply the Plan
terraform apply
You’ll see a detailed plan, and when prompted, type:
yes
Once completed, you’ll get confirmation that resources were created:
Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
Later, to add the EC2 instance:
terraform apply
Output:
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Success! You now have a fully functional VPC with an EC2 instance in the public subnet.
Main points
A custom VPC with CIDR
10.0.0.0/16
One private and one public subnet
An Internet Gateway connected to the public subnet
A Route Table for internet access
A t2.micro EC2 instance deployed in the public subnet
Cleanup (Optional)
When you're done testing, clean up the resources to avoid unnecessary costs:
terraform destroy
Thanks for Reading!
Hope this gives you some perspective.
Coming Up Next:
More hands-on cloud projects and DevOps tips — stay tuned!
Let’s Connect:
Share your thoughts in the comments or reach out on LinkedIn. Your feedback means a lot! You can also check out my work on GitHub.
Subscribe to my newsletter
Read articles from Soumen Bhunia directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Soumen Bhunia
Soumen Bhunia
Hello, my name is Soumen Bhunia, and I'm a student at a university with a focus on cybersecurity and advanced networking. My passion is using machine learning, cloud computing, DevOps, and MLOps to create systems that are intelligent, scalable, and secure. By incorporating automation and intelligence into every tier of digital infrastructure, I hope to address current cybersecurity issues.