# “🌐🌟Beginner’s Guide to Load Balancing on AWS Using NGINX and ALB”

### 🔰 Introduction

In this guide, I’ll walk you through how I deployed a basic NGINX web server setup using AWS services like EC2, ALB, Subnets, and VPC. Each server displays a simple custom message and the traffic is distributed using an Application Load Balancer. This small project helped me and you understand how load balancing works in AWS and how to connect multiple EC2 instances behind an ALB.

## 📑 **Index / Table of Contents**

1. **Introduction**  
     – Brief about the project and objective
    
2. **Architecture Overview**  
     – Visual diagram  
     – Basic AWS services used
    
3. **VPC and Subnet Setup**  
     – Create custom VPC  
     – Create 3 public subnets (in 3 AZs)  
     – Enable auto-assign public IP
    
4. **Internet Gateway and Routing**  
     – Create and attach IGW  
     – Route Table setup and association with subnets
    
5. **Security Groups Configuration**  
     – ALB Security Group  
     – EC2 Security Group
    
6. **Launching EC2 Instances**  
     – 3 Ubuntu instances  
     – Subnet & AZ mapping  
     – Key pair and public IPs
    
7. **Installing NGINX on EC2**  
     – Commands to install & start NGINX  
     – Enable on boot
    
8. **Customizing Web Content**  
     – Unique message per server (`Server 1`, `Server 2`, `Server 3`)
    
9. **Creating Application Load Balancer (ALB)**  
     – ALB across all 3 subnets  
     – Target group (port 80)  
     – Health checks & registration
    
10. **Testing the Setup**  
     – Access via ALB DNS  
     – Load balancing behavior
    
11. **Conclusion**
    

## 🧩 **1\. Introduction**

In this small project, I worked on deploying a simple web server setup using **NGINX on EC2 instances** behind an **Application Load Balancer (ALB)** in AWS. The goal was to understand how to:

* Launch EC2 instances across multiple subnets
    
* Install and configure NGINX on Ubuntu servers
    
* Set up an ALB to distribute incoming traffic
    
* Serve custom responses from each EC2 to test load balancing
    

Each server was placed in a different **Availability Zone** and returned a different message like “Server 1”, “Server 2”, and “Server 3” to help visualize ALB routing.

This project is ideal for beginners who want hands-on experience with core AWS services like **EC2, VPC, Subnets, IGW, Security Groups**, and **ALB**.

## 🗺️ **2\. Architecture Overview**

This project is built using basic yet important AWS services that work together to host a simple web application and distribute traffic across multiple servers.

---

### 🧱 **Main AWS Services Used:**

* **VPC** – Custom Virtual Private Cloud to isolate the network
    
* **Subnets** – 3 public subnets across different Availability Zones (AZs)
    
* **Internet Gateway (IGW)** – Allows internet access to instances
    
* **Route Table** – Connects subnets to the IGW for public access
    
* **EC2 Instances (Ubuntu)** – Hosts NGINX and serves static content
    
* **Security Groups** – Control inbound/outbound traffic to ALB and EC2
    
* **Application Load Balancer (ALB)** – Distributes HTTP traffic to EC2s
    
* **Target Group** – Links ALB to backend EC2 instances
    

---

### 🖼️ **Architecture Diagram:**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754301478647/9986f8ca-9273-4755-8ccb-5ea91f375ef4.png align="center")

This setup ensures that any request to the ALB is routed to one of the EC2 instances in a round-robin fashion. You can test this by hitting the ALB DNS in a browser and seeing different responses.

## 🌐 **3\. VPC and Subnet Setup**

The first step in deploying any AWS infrastructure is creating a **VPC (Virtual Private Cloud)**, which acts like your private network in the cloud.

In this setup, we create one VPC and divide it into 3 **public subnets**, each in a different **Availability Zone (AZ)** for better availability and distribution.

---

### 🧱 **3.1 Create Custom VPC**

1. Go to the **VPC Dashboard** in AWS.
    
2. Click **“Create VPC”** and choose **VPC only**.
    
3. Enter:
    
    * **Name:** `server-vpc`
        
    * **IPv4 CIDR block:** `10.0.0.0/16`
        
    * Leave IPv6 and other options as default.
        
4. Click **Create VPC**.
    

---

### 🌍 **3.2 Create 3 Public Subnets**

Now create three subnets in **different AZs**:

| Subnet Name | AZ | CIDR Block |
| --- | --- | --- |
| Subnet-1 | ap-south-1a | `10.0.1.0/24` |
| Subnet-2 | ap-south-1b | `10.0.2.0/24` |
| Subnet-3 | ap-south-1c | `10.0.3.0/24` |

For each subnet:

1. Go to **Subnets → Create subnet**
    
2. Select the VPC you created.
    
3. Assign **AZ**, **name**, and **CIDR**.
    
4. ✅ **Enable Auto-assign public IPv4** for each subnet (important for public access).
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754301663158/ebbe32c9-4073-47b4-9fb8-61c58a213a99.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754301674475/29b7c6be-884c-417e-9529-d6f53e9884b3.png align="center")

## 🌐 **4\. Internet Gateway and Routing**

To allow EC2 instances in public subnets to connect to the internet (for updates, package installs, etc.), we need two things:

* An **Internet Gateway (IGW)**
    
* A **Route Table** that connects subnets to the IGW
    

---

### 🔌 **4.1 Create and Attach Internet Gateway (IGW)**

1. Go to **VPC Dashboard → Internet Gateways**
    
2. Click **Create Internet Gateway**
    
    * **Name:** `server-igw`
        
3. Once created, click **Actions → Attach to VPC**
    
    * Select your VPC (`server-vpc`)
        
    * Click **Attach**
        

---

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754301822981/47c1aa9f-9e8f-474e-aba9-a7234d6f8ff9.png align="center")

### 🧭 **4.2 Create Route Table for Public Access**

1. Go to **Route Tables → Create route table**
    
    * **Name:** `Public-RT`
        
    * Select your VPC (`My-VPC`)
        
2. Click **Create**
    

---

### ➕ **4.3 Add Route to IGW**

1. Open `Public-RT` → Go to **Routes → Edit routes**
    
2. Click **Add route**
    
    * **Destination:** `0.0.0.0/0`
        
    * **Target:** Select your **Internet Gateway (My-IGW)**
        
3. Click **Save changes**
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754301860701/bb54e52c-d8d4-4b2e-983f-3941b479c5c1.png align="center")

---

### 🔗 **4.4 Associate Route Table to Public Subnets**

1. Open `Public-RT` → Go to **Subnet Associations**
    
2. Click **Edit subnet associations**
    
3. Select all 3 public subnets:
    
    * `Subnet-1 (10.0.1.0/24)`
        
    * `Subnet-2 (10.0.2.0/24)`
        
    * `Subnet-3 (10.0.3.0/24)`
        
4. Save
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754301904545/00d56c89-8425-4b83-82d5-843076133cad.png align="center")

## 🔐 **5\. Security Groups Configuration**

Security Groups (SGs) in AWS act like **virtual firewalls** that control **inbound and outbound traffic** to your EC2 instances and Load Balancer.  
We’ll create **two separate SGs** — one for the ALB and one for the EC2 instances.

---

### 🛡️ **5.1 Create ALB Security Group**

This SG allows the ALB to accept incoming HTTP requests from the internet.

1. Go to **EC2 → Security Groups → Create Security Group**
    
2. Name: `ALB-SG`
    
3. Description: `Allows HTTP access from anywhere`
    
4. VPC: Select `server-vpc`
    
5. Add Inbound Rule:
    
    * **Type:** HTTP
        
    * **Port:** 80
        
    * **Source:** Anywhere (`0.0.0.0/0`)
        
6. Leave outbound as default
    
7. Click **Create Security Group**
    

---

### 🖥️ **5.2 Create EC2 Security Group**

This SG allows EC2 instances to accept traffic **only from the ALB**, not directly from the internet.

1. Create another SG: `EC2-SG`
    
2. Description: `Allows HTTP from ALB only`
    
3. VPC: Select `My-VPC`
    
4. Add Inbound Rule:
    
    * **Type:** HTTP
        
    * **Port:** 80
        
    * **Source:** Custom
        
    * **Select ALB-SG** as source (it will show in the dropdown)
        
5. Click **Create Security Group**
    

---

### 🔄 **Attach SGs to Resources**

* While creating the **ALB**, attach `ALB-SG`
    
* While launching each **EC2 instance**, attach `EC2-SG`
    

## 💻 **6\. Launching EC2 Instances**

Now that our networking and security are in place, it's time to launch **3 EC2 instances** one in each public subnet — to host our NGINX web servers.

We’ll use **Ubuntu 22.04** as the OS for simplicity and compatibility.

---

### 🔸 **6.1 Launch EC2 Instances (Repeat 3 Times)**

1. Go to **EC2 → Instances → Launch Instance**
    
2. Enter:
    
    * **Name:** `Server-1` (change to Server-2 and Server-3 for others)
        
    * **AMI:** Ubuntu Server 22.04 LTS (64-bit)
        
    * **Instance type:** `t2.micro` (free tier eligible)
        
3. **Key Pair:** Select an existing one or create a new one  
    *(Make sure to download and keep the* `.pem` file safe)
    

---

### 📍 **6.2 Network Settings per Instance**

For each instance:

| Server Name | Subnet | Availability Zone |
| --- | --- | --- |
| Server-1 | `Subnet-1` | `ap-south-1a` |
| Server-2 | `Subnet-2` | `ap-south-1b` |
| Server-3 | `Subnet-3` | `ap-south-1c` |

* **Auto-assign Public IP:** Enabled ✅
    
* **Security Group:** Attach the `EC2-SG` you created earlier
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754302298520/23adbd07-edce-4968-a609-19c574dab3d6.png align="center")

---

### 🟢 **6.3 Launch All Instances**

1. Launch each instance with its respective subnet
    
2. Wait for **running status**
    
3. Copy the **public IP** of each instance (we’ll use them to SSH and install NGINX)
    

## 🔧 **7\. Installing NGINX on EC2**

After your EC2 instances are running, SSH into each one and install NGINX:

```powershell
# Update and install NGINX
sudo apt update -y
sudo apt install nginx -y

# Start NGINX and enable on boot
sudo systemctl start nginx
sudo systemctl enable nginx
```

Repeat the above steps on all 3 EC2 instances.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754302494147/235a8b2a-3e46-4099-b43c-dc64e14bd10a.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754302524717/9fdb2180-242d-4d4c-b251-92282bd0d6ee.png align="center")

---

## 🎨 **8\. Customizing Web Content**

We want each EC2 instance to return a unique message (e.g., Server 1, Server 2, etc.) so we can test the ALB behavior.

### On Server 1:

```powershell
echo "Server 1" | sudo tee /var/www/html/index.nginx-debian.html
```

### On Server 2:

```powershell
echo "Server 2" | sudo tee /var/www/html/index.nginx-debian.html
```

### On Server 3:

```powershell
echo "Server 3" | sudo tee /var/www/html/index.nginx-debian.html
```

---

## ⚙️ **9\. Creating Application Load Balancer (ALB)**

Now we create an **Application Load Balancer** that will distribute incoming traffic across the 3 servers.

### 🔹 ALB Setup:

1. Go to **EC2 → Load Balancers → Create Load Balancer**
    
2. Choose **Application Load Balancer**
    
3. Enter:
    
    * **Name:** `server-alb`
        
    * **Scheme:** Internet-facing
        
    * **Listeners:** HTTP (Port 80)
        
4. **Availability Zones**: Select your VPC and the 3 subnets:
    
    * Subnet-1 (ap-south-1a)
        
    * Subnet-2 (ap-south-1b)
        
    * Subnet-3 (ap-south-1c)
        
5. Attach **ALB-SG** as the security group.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754302553431/813ae09a-f884-46db-b9f8-3c017108ac35.png align="center")

---

### 🔸 Target Group Setup:

1. Create a new **Target Group**
    
    * **Target type:** Instances
        
    * **Protocol:** HTTP
        
    * **Port:** 80
        
2. Register all 3 EC2 instances
    
3. Keep health checks as default (or use `/`)
    

Once done, the ALB will start running and routing traffic.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754302611516/ebd282ef-6ace-4e7a-b5ea-98e5177faa59.png align="center")

---

## 🔍 **10\. Testing the Setup**

After your ALB status is **active**:

1. Go to **Load Balancers → Select your ALB**
    
2. Copy the **DNS name** (e.g., [`my-alb-123456789.ap-south-1.elb.amazonaws.com`](http://my-alb-123456789.ap-south-1.elb.amazonaws.com))
    
3. Open it in your browser:
    

```powershell
http://<your-alb-dns>
```

🌀 Refresh multiple times — you should see:

* Server 1
    
* Server 2
    
* Server 3
    

This confirms **round-robin load balancing** is working across your EC2 instances

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754302670183/6275b256-bf82-4e32-88c9-2ebf40159048.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754302684340/4a2a48ab-6b46-4d68-a3c7-b7441df70aaf.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1754302691303/fa2355e3-7dca-4727-b2c3-4600b528e1aa.png align="center")

## ✅ **Conclusion**

In this hands-on project, we successfully created a load-balanced web server architecture on AWS using core services like **VPC, EC2, Subnets, Security Groups**, and an **Application Load Balancer (ALB)**.

Each EC2 instance ran **NGINX**, hosted a unique web page, and was deployed in a separate **Availability Zone**, ensuring high availability and better traffic distribution. The ALB handled incoming traffic and distributed it across the servers in a **round-robin** fashion — a basic yet powerful demonstration of load balancing on AWS.

This project gave me a practical understanding of:

* How networking works in AWS (VPC, Subnets, IGW, Routing)
    
* How to configure EC2 and secure them with Security Groups
    
* How to use ALB to manage and balance web traffic
    
* How to test and validate a real cloud setup end-to-end
    

## **👨‍💻 About the Author**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&format=webp&auto=compress,format&format=webp&auto=compress,format&format=webp align="left")

This series isn't just about using AWS; it's about **mastering the core services that power modern cloud infrastructure**.

---

### 📬 Let's Stay Connected

* 📧 **Email**: [**gujjarapurv181@gmail.com**](mailto:gujjarapurv181@gmail.com)
    
* 🐙 **GitHub**: [**github.com/ApurvGujjar07**](http://github.com/ApurvGujjar07)
    
* 💼 **LinkedIn**: [**linkedin.com/in/apurv-gujjar**](http://linkedin.com/in/apurv-gujjar)
