Ex.
12 Configure public Virtual Private Cloud with one public subnet and one
private subnet then launch &access any virtual machine within
the private subnet
Aim
To Configure public Virtual Private Cloud with one public subnet and one
private subnet then launch &access any virtual machine
within the private subnet
Algorithm
Steps to Configure
1️. Create VPC & Subnets
● Create a VPC with CIDR 10.0.0.0/16
● Create a Public Subnet (10.0.1.0/24)
● Create a Private Subnet (10.0.2.0/24)
2️. Setup Networking
● Attach an Internet Gateway for public access.
● Create a Route Table for the public subnet to allow internet traffic.
● Create a NAT Gateway in the public subnet so that private instances can access the
internet securely.
● Create a Route Table for the private subnet to send outbound traffic via the NAT
Gateway.
3️. Security Groups
● Bastion Host Security Group (allows SSH from anywhere).
● Private EC2 Security Group (allows SSH only from the Bastion Host).
4️. Deploy EC2 Instances
● Bastion Host in the public subnet (to act as a jump server).
● Private EC2 Instance in the private subnet (no direct internet access).
5.Connect to Private EC2
● SSH into Bastion Host and then into the Private EC2 instance.
Terraform Code (main.tf)
Save this as main.tf and modify values as needed.
provider "aws" {
region = "us-east-1" # Change as needed
}
# 1️.Create VPC
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "MyVPC"
}
}
# 2️.Create Public Subnet
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
availability_zone = "us-east-1a"
tags = {
Name = "PublicSubnet"
}
}
# 3️. Create Private Subnet
resource "aws_subnet" "private_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "PrivateSubnet"
}
}
# 4️.Create Internet Gateway
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.my_vpc.id
tags = {
Name = "InternetGateway"
}
}
# 5️.Route Table for Public Subnet (Internet Access)
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "PublicRouteTable"
}
}
# 6️.Associate Public Route Table with Public Subnet
resource "aws_route_table_association" "public_assoc" {
subnet_id = aws_subnet.public_subnet.id
route_table_id = aws_route_table.public_rt.id
}
# 7️.Create Elastic IP for NAT Gateway
resource "aws_eip" "nat_eip" {
domain = "vpc"
}
# 8️.Create NAT Gateway (for Private Subnet Internet Access)
resource "aws_nat_gateway" "nat_gw" {
allocation_id = aws_eip.nat_eip.id
subnet_id = aws_subnet.public_subnet.id
tags = {
Name = "NATGateway"
}
}
# 9️.Create Route Table for Private Subnet (NAT Gateway for Internet Access)
resource "aws_route_table" "private_rt" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_gw.id
}
tags = {
Name = "PrivateRouteTable"
}
}
# 10. Associate Private Route Table with Private Subnet
resource "aws_route_table_association" "private_assoc" {
subnet_id = aws_subnet.private_subnet.id
route_table_id = aws_route_table.private_rt.id
}
# 11.Security Group for Bastion Host (Allows SSH from Anywhere)
resource "aws_security_group" "bastion_sg" {
vpc_id = aws_vpc.my_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 = "BastionSecurityGroup"
}
}
# 1️2. Security Group for Private EC2 (Only Allows SSH from Bastion)
resource "aws_security_group" "private_sg" {
vpc_id = aws_vpc.my_vpc.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [aws_security_group.bastion_sg.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "PrivateSecurityGroup"
}
}
# 1️3. Create Key Pair
resource "aws_key_pair" "my_key" {
key_name = "my-key"
public_key = file("~/.ssh/id_rsa.pub")
}
# 1️4.Launch Bastion Host in Public Subnet
resource "aws_instance" "bastion" {
ami = "ami-0c02fb55956c7d316"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet.id
key_name = aws_key_pair.my_key.key_name
security_groups = [aws_security_group.bastion_sg.name]
tags = {
Name = "BastionHost"
}
}
# 1️5.Launch Private EC2 Instance in Private Subnet
resource "aws_instance" "private_ec2" {
ami = "ami-0c02fb55956c7d316"
instance_type = "t2.micro"
subnet_id = aws_subnet.private_subnet.id
key_name = aws_key_pair.my_key.key_name
security_groups = [aws_security_group.private_sg.name]
tags = {
Name = "PrivateEC2"
}
}
# 1️6.Output Bastion Host Public IP
output "bastion_public_ip" {
value = aws_instance.bastion.public_ip
}
Steps to Deploy
1️.Initialize Terraform
Bash
terraform init
2️.Plan
bash
terraform plan
3️.Apply
bash
terraform apply -auto-approve
4️.Get Bastion Host Public IP
bash
terraform output bastion_public_ip
5️.SSH into Bastion Host
bash
ssh -i ~/.ssh/id_rsa ec2-user@<bastion_public_ip>
6️.From Bastion, SSH into Private EC2
bash
ssh -i ~/.ssh/id_rsa
[email protected] # Use private IP of EC2
Result
Thus public Virtual Private Cloud with one public subnet and one private
subnet was configured then &access in any virtual machine within the private subnet
was launched successfully.