Two-Tier Website Deployment on AWS using EC2, RDS and ALB

2.1 Project Overview

Overview of Project ☁️

This project involves deploying a To-Do List web application using a two-tier architecture on AWS. The architecture is designed for scalability, security, and cost-effectiveness by leveraging EC2 instances for the application layer and Amazon RDS for the database layer, with an Application Load Balancer (ALB) to distribute traffic.

  • Application Layer: Two EC2 instances host the Node.js application, ensuring high availability.

  • Database Layer: Amazon RDS is used to manage a MySQL database, storing application data securely.

  • Load Balancing & Routing: An Application Load Balancer (ALB) distributes incoming requests across both EC2 instances for fault tolerance.

  • Security & Networking: Security Groups, IAM roles, and VPC configurations are implemented for secure communication between components.

Services Used 🛠

  1. Amazon EC2: Hosts the web application on two instances for redundancy and performance. [Compute]

  2. Amazon RDS: Provides a managed relational database (MySQL) for application data. [Database]

  3. Application Load Balancer (ALB): Distributes traffic across EC2 instances for scalability and reliability. [Networking]

  4. Amazon VPC: Ensures secure networking with separate subnets for EC2 and RDS. [Networking]

  5. IAM Roles and Policies: Grants necessary permissions for secure interactions between services. [Security]

  6. Security Groups: Controls traffic flow between ALB, EC2, and RDS to enforce security. [Security]

Architectural Diagram ✍️

2.2 Pre-Requisites

Steps to be Performed 👩‍💻

  1. AWS Account

  2. Installing SQL Client

  3. Cloning the To-Do List Application Code

#1 AWS Account

  • Sign in to your existing AWS account, or create a new one here.

  • Ensure your account has permissions to create and manage Elastic Beanstalk, Amazon RDS, VPC, and related resources.

#2 Installing SQL Client

You'll need an SQL client to connect to the RDS database. Follow the steps for your operating system:

For Windows:

  • Download MySQL Installer from here.

  • Run the installer and select MySQL Workbench during the setup.

  • Complete the installation.

  • Open MySQL Workbench and verify the installation.

For Linux:

  • Open your terminal.

  • Install MySQL Workbench using the following command:

For Red Hat-based distros (e.g., CentOS):

  • Launch MySQL Workbench from the applications menu.

For macOS:

  • Download MySQL Workbench DMG from here.

  • Open the downloaded file and drag MySQL Workbench to the Applications folder.

  • Open MySQL Workbench and verify the installation.

#3 Cloning the To-Do List Application Code

The source code for the to-do list application is available. Follow these steps to clone the repository:

1. Install Git if it's not already installed:

  • For Windows: Download and install Git from here.

  • For Linux:

  • For macOS:

2. Clone the repository using the following command:

3. Navigate to the cloned directory:

2.3 Setup VPC and Networking

Steps to be Performed 👩‍💻

  1. Create a VPC

  2. Create Public and Private Subnets

  3. Create an Internet Gateway (IGW)

  4. Configure Route Tables

  5. Configure Security Groups

#1 Create a VPC

To create a secure and isolated environment for your application and database, we'll set up a Virtual Private Cloud (VPC) and configure networking components, ensuring high availability with multiple subnets across two availability zones.

  • Log in to the AWS Management Console.

  • Navigate to the VPC Dashboard.

  • Click Create VPC and select VPC only.

  • Configure the following settings:

    • Name tag: TodoAppVPC

    • IPv4 CIDR block: 10.0.0.0/16

    • IPv6 CIDR block: No IPv6 CIDR block.

    • Tenancy: Default.

  • Click Create VPC.

#2 Create Public and Private Subnets

Create four subnets across two availability zones—two subnets for the application layer (public subnets) and two subnets for the database layer (private subnets).

For Availability Zone 1 (us-east-1a):

  • Go to Subnets and click Create subnet

  • Configure the following settings for the public subnet:

    • Name tag: TodoApp-Subnet-Public-A

    • VPC ID: Select TodoAppVPC

    • Availability Zone: us-east-1a

    • IPv4 CIDR block: 10.0.1.0/24

  • Click on Add new subnet.

  • Create a private subnet in the same Availability Zone:

    • Name tag: TodoApp-Subnet-Private-A

    • VPC ID: Select TodoAppVPC

    • Availability Zone: us-east-1a

    • IPv4 CIDR block: 10.0.2.0/24

  • Click on Add new subnet.

For Availability Zone 2 (us-east-1b):

  • Repeat the process for public subnet in us-east-1b:

    • Name tag: TodoApp-Subnet-Public-B

    • VPC ID: Select TodoAppVPC

    • Availability Zone: us-east-1b

    • IPv4 CIDR block: 10.0.3.0/24

  • Click Create subnet. Ensure you have 4 subnets created:

  • Create a private subnet in us-east-1b:

    • Name tag: TodoApp-Subnet-Private-B

    • VPC ID: Select TodoAppVPC

    • Availability Zone: us-east-1b

    • IPv4 CIDR block: 10.0.4.0/24

#3 Create an Internet Gateway (IGW)

  • Go to Internet Gateways in the VPC Dashboard.

  • Click Create internet gateway.

  • Enter a name tag: TodoApp-IGW.

  • Click Create internet gateway.

  • Attach the IGW to the TodoAppVPC:

    • Select the created IGW.

    • Click Actions > Attach to VPC and choose TodoAppVPC.

#4 Configure Route Tables

We need to configure Route tables to handle the communication between these subnets. To do this-

For Public Subnets:

1. In the VPC Dashboard, go to Route Tables.

2. Click Create route table.

3. Configure the following settings:

  • Name tag: TodoApp-Public-Route-Table

  • VPC: Select TodoAppVPC

4. Click Create route table.

5. Add a route to the IGW:

  • Select the route table and click the Routes tab.

  • Click Edit routes and add:

    • Destination: 0.0.0.0/0.

    • Target: Select the TodoApp-IGW.

  • Click Save routes.

6. Associate the public subnets (TodoApp-Subnet-Public-A and TodoApp-Subnet-Public-B) with this route table:

  • Go to the Subnet Associations tab.

  • Click Edit subnet associations and select both TodoApp-Subnet-Public-A and TodoApp-Subnet-Public-B.

  • Click Save associations.

For Private Subnets:

1. Create a new route table for the private subnets (no IGW access).

  • Click Create route table.

  • Name tag: TodoApp-Private-Route-Table

  • VPC: Select TodoAppVPC

2. Click Create route table.

3. Associate the private subnets (TodoApp-Subnet-Private-A and TodoApp-Subnet-Private-B) with this route table:

  • Go to the Subnet Associations tab.

  • Click Edit subnet associations and select both TodoApp-Subnet-Private-A and TodoApp-Subnet-Private-B.

  • Click Save associations.

#5 Configure Security Groups

Lets create Security Groups for Webserver instances and the Database to be associated with the public and private subnets respectively. To do this—

1. Go to Security Groups in the VPC Dashboard.

2. Create a Security Group for Web Server

  • Go to the AWS Management Console → Navigate to EC2Security Groups.

  • Click Create Security Group and configure as follows:

  • Name: Webserver-SG

  • VPC: Select the correct VPC.

  • Configure Inbound Rules

Click Create Security Group.

3. Create a security group for the database layer:

  • Name tag: TodoApp-Database-SG

  • VPC: Select TodoAppVPC

4. Add the following inbound rules:

  • Type: MySQL/Aurora

  • Protocol: TCP

  • Port Range: 3306

  • Source: Select Webserver-SG

5.4 Database Layer - Setup RDS

Steps to be Performed 👩‍💻

  1. Create an RDS Instance

  2. Connect to the RDS Database Using Bastion Host

  3. Create the Database Schema

#1 Create an RDS Instance

In this step, we'll configure an Amazon RDS MySQL instance using the free-tier option to serve as the database for your to-do list application. You will also learn how to connect to it using a MySQL client. To do this—

  • Log in to the AWS Management Console

    • Go to the RDS Dashboard by searching for “RDS” in the AWS Console.

  • Create a New Database

    • Click on Create database to begin the setup.

  • Select Database Engine

    • Choose MySQL as the database engine. This is the database for your to-do list application.

  • Engine version: Choose the default MySQL version.

  • Template: Select Free Tier to ensure the instance is eligible for the AWS Free Tier.

  • Configure Database SettingsDB Instance Identifier: Enter a unique name for your database, such as todo-instance.

    • Master username: Choose a username (e.g., admin).

    • Master password: Create a strong password (note it down).

    • Confirm password: Re-enter the password.

  • Configure Instance Specifications

    • DB Instance Class: Keep it as default.

  • Set Up Connectivity

    • VPC: Select the VPC you created earlier (TodoAppVPC).

    • Subnet group: Choose a subnet group that includes your private subnets (this ensures the database will be accessible only from within the VPC).

    • Publicly Accessible: Select No (this ensures the database is not publicly accessible).

    • VPC Security Group: Select the security group you created earlier (TodoApp-Database-SG), allowing access from the application layer.

  • Create the Database

    • Click Create database to launch the instance. It will take a few minutes for the instance to be provisioned and available.

#2 Connect to the RDS Database Using Bastion Host

Since your RDS instance is in a private subnet, you cannot directly connect to it from outside the VPC. Instead, you will use a Bastion Host (an EC2 instance in a public subnet) to securely access the RDS instance.

1. Launch an EC2 Instance in the public subnet of your VPC. This instance will act as your Bastion Host.

  • Go to the EC2 Dashboard and click on Launch Instance.

  • Choose an appropriate Amazon Machine Image (AMI)— Amazon Linux 2.

  • Select an instance type (e.g., t2.micro for free tier eligibility).

  • In the Key-pair section, create a new Key pair and give a suitable name to it (For e.g. bastion-host-key). The bastion-host-key.pem file gets downloaded which can be used to SSH into the instances in the further steps

  • In the Network section, select your VPC and the public subnet where the Bastion Host will reside.

  • Make sure the Auto-assign Public IP option is enabled so that the Bastion Host can be accessed from the public internet.

  • For Security Group, you can choose the Webserver-SG

  • Leave the rest as defaults and click on Create Instance.

2. SSH into the Bastion Host

Once the EC2 instance is up and running, you can connect to it via SSH.

  • Open your terminal and use the following SSH command to connect to the Bastion Host.

  • Replace /path/to/your/key.pem with the actual path to your downloaded SSH key file, and <Bastion-Host-EIP> with the public IP of the Bastion Host.

  • Type yes when it asks— Are you sure you want to continue connecting.

  • You have successfully connected to a Bastion Host.

3. Install MySQL Client on the Bastion Host

To interact with your MySQL RDS instance, you need to install the MySQL client on the Bastion Host.

  • For Amazon Linux 2 (or similar):

4. Connect to the RDS Instance from the Bastion Host

  • Now that you installed MySQL client on Bastion Host, you can securely connect to your RDS instance using the MySQL client.

  • Use the following command to connect:

  • After running the command, you will be prompted to enter the password for the master username. Enter the password you created earlier.

  • Once connected, you should see the MySQL prompt (mysql>). You can now execute SQL queries.

#3 Create the Database Schema

1. Access the Database

After successfully connecting to the RDS instance, create a new database for your application:

2. Create the Tables

For your to-do list application, create the necessary tables. Here’s an example SQL statement for creating a Tasks table:

5.5 Application Layer - Setup EC2 and Load Balancer

Steps to be Performed 👩‍💻

  1. Launch two EC2 Instances

  2. Install Dependencies and Setup the Code

  3. Setup a Load Balancer

#1 Launch Two EC2 Instances

We will be creating two EC2 instances to be added

1. Navigate to EC2 Dashboard

  • Go to the AWS Management Console → Search for EC2.

  • Click Launch Instance.

  • Provide an appropriate name (For ex: web-server-1)

2. Configure Instance Details

  • Choose an Amazon Machine Image (AMI). Select Amazon Linux.

  • Select an Instance Type. Choose t2.micro (free tier eligible).

  • Key pair: You can use the same key pair that you used for the Bastion Host.

    • Network & Subnet ConfigurationVPC: Select TodoAppVPC.

    • Subnet: Choose a public subnet. [Public Subnet A]

    • Auto-assign Public IP: Enable

    • Choose the Webserver SG created earlier.

  • Leave the rest as defaults and click on Create Instance.

  • Repeat the process to launch a second EC2 instance (web-server-2) in another public subnet [Public subnet B].

#2 Install Dependencies and Setup the Code

Let us setup the todo list code in the EC2 instances. To do this—

1. Connect to Each EC2 Instance

  • Get the Public IP of an EC2 instance from the AWS Console and SSH into it:

Repeat for the second instance on a new terminal window. You can perform all the below operations simultaneously on both the EC2 instances.

2. Update Packages & Install Node.js

3. Clone the Node.js Application from GitHub

  • Navigate to the home directory and clone the backend repository:

4. Create a .env File

  • Inside the project directory, create a .env file with your database details:

  • Add the following contents (replace placeholders with actual values):

  • Save the file (CTRL+X → Y → ENTER).

5. Install Dependencies

  • Use PM2 to Keep the App Running

  • Install PM2 (a process manager for Node.js apps):

7. Configure Nginx as a Reverse Proxy

  • Delete the default Nginx config:

  • Create a new Nginx configuration file:

  • Add the following code in the file:

  • Save and exit (CTRL + X, then Y, then ENTER).

8. Restart Nginx to Apply Changes

9. Check the status of Nginx:

10. Access the application using the Public IP of your EC2 instance in a browser:

If everything is set up correctly, your To-Do App should be displayed!

11. Repeat the process on the second EC2 instance

  • Connect via SSH.

  • Install Node.js, Git, and Nginx.

  • Clone the GitHub repo.

  • Install dependencies, start the app, and configure Nginx.

#3 Setup a Load Balancer

Since we have two EC2 instances, we need to configure an Application Load Balancer (ALB) to distribute traffic evenly between them. Follow these steps to set it up:

1. Navigate to Load Balancers

  • Go to AWS Management Console → Search for EC2.

  • In the left sidebar, click Load Balancers.

  • Click Create Load Balancer.

2. Select Load Balancer Type

  • Choose Application Load Balancer (ALB).

  • Click Create.

3. Configure Load Balancer

  • Basic Configuration

    • Name: TodoApp-ALB

    • Scheme: Internet-facing

    • IP Address Type: IPv4

  • Network Settings

    • VPC: Select TodoAppVPC.

    • Availability Zones: Select two public subnets (the ones where your EC2 instances are running).

  • Listeners

    • Protocol: HTTP

    • Port: 80

    • Click Next.

4. Configure Security Group

  • Choose Create a New Security Group.

  • Name it ALB-SG.

  • Select the appropriate VPC.

  • Add the following inbound rules:

  • Navigate back to the ALB creation and select the newly created ALB-SG.

5. Configure Target Group

  • In Listeners and Routing section, The ALB will ask you to select a Target Group, for that click on Create Target Group.

  • Target Group Name: TodoApp-TG

  • Target Type: Instance

  • Protocol: HTTP

  • Port: 80

  • Health Check:

    • Path: /

    • Protocol: HTTP

  • Click Next.

  • Register EC2 Instances

    • Select both web-server-1 and web-server-2.

    • Click Add to registered → Click Create Target Group, navigate back to the Load Balancer page and select the recently created Target Group.

6. Review & Create Load Balancer

  • Review all configurations.

  • Click Create Load Balancer.

  • Wait a few minutes for the ALB to be provisioned.

7. Test the Setup

  • Find the DNS name of the ALB from the Load Balancer console.

  • Open it in a browser:

  • You should see your Todo App running!

This brings us to the completed Two Tier Deployment of a Todo list application on AWS!