✅ TASK 2 — Build a VPC With EC2 (Step-by-Step Guide)
Folder structure:
terraform-vpc/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
STEP 1 — Create main.tf
provider "aws" {
region = var.aws_region
}
# -----------------------
# VPC
# -----------------------
resource "aws_vpc" "main_vpc" {
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "main-vpc"
}
}
# -----------------------
# Public Subnet
# -----------------------
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.main_vpc.id
cidr_block = var.public_subnet_cidr
map_public_ip_on_launch = true
availability_zone = var.az
tags = {
Name = "public-subnet"
}
}
# -----------------------
# Internet Gateway
# -----------------------
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main_vpc.id
tags = {
Name = "main-igw"
}
}
# -----------------------
# Route Table
# -----------------------
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.main_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "public-route-table"
}
}
# -----------------------
# Route Table Association
# -----------------------
resource "aws_route_table_association" "public_assoc" {
subnet_id = aws_subnet.public_subnet.id
route_table_id = aws_route_table.public_rt.id
}
# -----------------------
# Security Group
# -----------------------
resource "aws_security_group" "ec2_sg" {
name = "ec2_public_sg"
description = "Allow SSH"
vpc_id = aws_vpc.main_vpc.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "EC2 Public SG"
}
}
# -----------------------
# Key Pair
# -----------------------
resource "aws_key_pair" "my_key" {
key_name = "task2-key"
public_key = file(var.public_key_path)
}
# -----------------------
# EC2 Instance
# -----------------------
resource "aws_instance" "public_ec2" {
ami = var.ami_id
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet.id
key_name = aws_key_pair.my_key.key_name
vpc_security_group_ids = [aws_security_group.ec2_sg.id]
tags = {
Name = "public-ec2"
}
}
STEP 2 — Create variables.tf
variable "aws_region" {
type = string
}
variable "vpc_cidr" {
type = string
}
variable "public_subnet_cidr" {
type = string
}
variable "az" {
type = string
}
variable "ami_id" {
type = string
}
variable "public_key_path" {
type = string
}
STEP 3 — Create outputs.tf
output "vpc_id" {
value = aws_vpc.main_vpc.id
}
output "public_subnet_id" {
value = aws_subnet.public_subnet.id
}
output "ec2_public_ip" {
value = aws_instance.public_ec2.public_ip
}
STEP 4 — Create terraform.tfvars
aws_region = "ap-south-1"
vpc_cidr = "10.0.0.0/16"
public_subnet_cidr = "10.0.1.0/24"
az = "ap-south-1a"
ami_id = "ami-0f5ee92e2d63afc18"
public_key_path = "~/.ssh/id_rsa.pub"
STEP 5 — Initialize Terraform
terraform init
STEP 6 — Validate Configuration
terraform validate
STEP 7 — Generate Execution Plan
terraform plan
STEP 8 — Apply and Build VPC + EC2
terraform apply
Type yes.
🎉 RESULT
Terraform will create:
✔ VPC
✔ Public Subnet
✔ Internet Gateway
✔ Route Table
✔ Route Table Association
✔ Security Group
✔ Key Pair
✔ EC2 Instance in Public Subnet
You will get:
ec2_public_ip = "13.x.x.x"
SSH into EC2:
ssh -i ~/.ssh/id_rsa ec2-user@<PUBLIC-IP>
🎉 RESULT
+ region = "ap-south-1"
+ tags_all = (known after apply)
}
# aws_route_table.public_rt will be created
+ resource "aws_route_table" "public_rt" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ region = "ap-south-1"
+ route = [
+ {
+ cidr_block = "0.0.0.0/0"
+ gateway_id = (known after apply)
# (11 unchanged attributes hidden)
},
]
+ tags = {
+ "Name" = "public-route-table"
}
+ tags_all = {
+ "Name" = "public-route-table"
}
+ vpc_id = (known after apply)
}
# aws_route_table_association.public_assoc will be created
+ resource "aws_route_table_association" "public_assoc" {
+ id = (known after apply)
+ region = "ap-south-1"
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# aws_security_group.ec2_sg will be created
+ resource "aws_security_group" "ec2_sg" {
+ arn = (known after apply)
+ description = "Allow SSH"
+ egress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = false
+ to_port = 0
# (1 unchanged attribute hidden)
},
]
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ from_port = 22
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 22
# (1 unchanged attribute hidden)
},
]
+ name = "ec2_public_sg"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ region = "ap-south-1"
+ revoke_rules_on_delete = false
+ tags = {
+ "Name" = "EC2 Public SG"
}
+ tags_all = {
+ "Name" = "EC2 Public SG"
}
+ vpc_id = (known after apply)
}
# aws_subnet.public_subnet will be created
+ resource "aws_subnet" "public_subnet" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "ap-south-1a"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.0.1.0/24"
+ enable_dns64 = false
+ enable_resource_name_dns_a_record_on_launch = false
+ enable_resource_name_dns_aaaa_record_on_launch = false
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ ipv6_native = false
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ private_dns_hostname_type_on_launch = (known after apply)
+ region = "ap-south-1"
+ tags = {
+ "Name" = "public-subnet"
}
+ tags_all = {
+ "Name" = "public-subnet"
}
+ vpc_id = (known after apply)
}
# aws_vpc.main_vpc will be created
+ resource "aws_vpc" "main_vpc" {
+ arn = (known after apply)
+ cidr_block = "10.0.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_dns_hostnames = true
+ enable_dns_support = true
+ enable_network_address_usage_metrics = (known after apply)
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_network_border_group = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ region = "ap-south-1"
+ tags = {
+ "Name" = "main-vpc"
}
+ tags_all = {
+ "Name" = "main-vpc"
}
}
Plan: 8 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ ec2_public_ip = (known after apply)
+ public_subnet_id = (known after apply)
+ vpc_id = (known after apply)
Top comments (0)