DevOps Project 5Terraform + AWS

VPC Architecture Demo

A full-stack demonstration of a secure 2-tier architecture on AWS. Frontend in Public Subnet communicating with Backend in Private Subnet.

Live Connectivity Test

Click the button below to send a request from this Frontend Server (Public) to the Backend Server (Private IP: 10.0.2.20).

AWS VPC Architecture

VPC: 10.0.0.0/16
Internet Gateway
Public Subnet (10.0.1.0/24)
Frontend EC2
IPPublic
Ports80/443
StackNext.js
SG-Frontend
Traffic
Private Subnet (10.0.2.0/24)
Backend EC2
IP10.0.2.20
Port8000
StackFastAPI
SG-Backend
main.tf Code Viewer
Hover over code blocks to understand their purpose.
# AWS Provider
provider "aws" {
  region = "us-west-2"
}
# VPC Resource
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "devops-project-5"
  }
}
# Public and Private Subnets
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = true
  availability_zone       = "us-west-2a"

  tags = {
    Name = "devops-project-5-public-subnet"
  }
}

resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-west-2a"

  tags = {
    Name = "devops-project-5-private-subnet"
  }
}
# Internet Gateway
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "devops-project-5-igw"
  }
}
# NAT Gateway & Elastic IP
resource "aws_eip" "nat_ip" {
  domain = "vpc"
}

resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat_ip.id
  subnet_id     = aws_subnet.public.id

  tags = {
    Name = "devops-project-5-nat"
  }
}
# Route Tables
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 = "devops-project-5-public-rt"
  }
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.nat.id
  }

  tags = {
    Name = "devops-project-5-private-rt"
  }
}
# Route Table Associations
resource "aws_route_table_association" "public_assoc" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "private_assoc" {
  subnet_id      = aws_subnet.private.id
  route_table_id = aws_route_table.private.id
}
# Frontend Security Group
resource "aws_security_group" "frontend_sg" {
  name   = "frontend-sg"
  vpc_id = aws_vpc.main.id

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

  ingress {
    description = "Allow HTTPS"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "Allow Next.js"
    from_port   = 3000
    to_port     = 3000
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "Allow SSH"
    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 = "frontend-sg"
  }
}
# Backend Security Group
resource "aws_security_group" "backend_sg" {
  name   = "backend-sg"
  vpc_id = aws_vpc.main.id

  ingress {
    description     = "Allow backend requests from frontend SG"
    from_port       = 8000
    to_port         = 8000
    protocol        = "tcp"
    security_groups = [aws_security_group.frontend_sg.id]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "backend-sg"
  }
}
# Backend EC2 Instance
resource "aws_instance" "backend" {
  ami                    = "ami-0892d3c7ee96c0bf7"
  instance_type          = "t2.micro"
  subnet_id              = aws_subnet.private.id
  private_ip             = "10.0.2.20"
  vpc_security_group_ids = [aws_security_group.backend_sg.id]

  user_data = file("user_data_backend.sh")

  tags = {
    Name = "backend-server"
  }
}
# Frontend EC2 Instance
resource "aws_instance" "frontend" {
  depends_on = [
    aws_instance.backend
  ]

  ami                    = "ami-0892d3c7ee96c0bf7"
  instance_type          = "t2.small"
  subnet_id              = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.frontend_sg.id]

  user_data = file("user_data_frontend.sh")

  tags = {
    Name = "frontend-server"
  }
}

Hover over the code blocks to see detailed explanations here.

Key Concepts

VPC (Virtual Private Cloud)

A logically isolated section of the AWS Cloud where you can launch AWS resources in a virtual network that you define.

CIDR Block

Classless Inter-Domain Routing. A method for allocating IP addresses and for IP routing.

Subnet

A range of IP addresses in your VPC. You can launch AWS resources into a specified subnet.

Internet Gateway

A horizontally scaled, redundant, and highly available VPC component that allows communication between your VPC and the internet.

NAT Gateway

A Network Address Translation (NAT) service. You can use a NAT gateway so that instances in a private subnet can connect to services outside your VPC but external services cannot initiate a connection with those instances.

Security Group

Acts as a virtual firewall for your EC2 instances to control incoming and outgoing traffic.

Getting Started

Configure Terraform

Learn how to install Terraform and configure it to manage your AWS infrastructure as code.

AWS Credentials

Set up your AWS credentials to allow Terraform and the CLI to interact with your account.

Project Screenshots

1. Terraform Init

Initializing the Terraform working directory and downloading providers.

1. Terraform Init
Click to expand
2. Terraform Plan

Previewing the changes that Terraform will make to the infrastructure.

2. Terraform Plan
Click to expand
3. Terraform Apply

Applying the configuration to create resources in AWS.

3. Terraform Apply
Click to expand