Deploying Scalable Applications in Private Subnets with Bastion Host and ALB on AWS

Ayush ShrotriyaAyush Shrotriya
5 min read

πŸš€ Deploying Web Apps in Private Subnets with Bastion Host and Load Balancer (Step-by-Step on AWS)

A complete walkthrough of deploying secure, auto-scaled web apps in private subnets using EC2, Auto Scaling, Load Balancer, and a Bastion Host β€” all inside a custom VPC.


🌐 Overview

In this blog, I'll walk you through how I created a secure AWS infrastructure where:

  • EC2 instances are in private subnets.

  • A bastion host is used to access them.

  • A Layer 7 (HTTP) Application Load Balancer routes traffic.

  • Auto Scaling Groups manage dynamic EC2 instances.

We’ll deploy a basic Python HTTP server in one EC2 instance and observe how load balancing works with public-facing ALBs routing to private instances.


🧱 Step 1: Create a VPC with Subnets

βœ… Create VPC:

  • Name: demo-vpc

  • CIDR: 10.0.0.0/16

βœ… Create Subnets:

  • Private Subnets:

    • private1-east-1a β†’ AZ: us-east-1a

    • private2-east-1b β†’ AZ: us-east-1b

  • Public Subnet:

    • public1-east-1a β†’ AZ: us-east-1a


πŸ“¦ Step 2: Launch Template for Auto Scaling

βœ… Create a Launch Template:

  • AMI: Ubuntu

  • Instance Type: t2.micro

  • Key Pair: east1key

  • Security Group: aws-prod-example

    • Allow SSH (port 22) from anywhere

    • Allow TCP 8000 (We'll secure this later) for web server


πŸ“ˆ Step 3: Auto Scaling Group (ASG)

βœ… Configure Auto Scaling Group:

  • Name: aws-prod-example

  • Launch Template: use the one above

  • VPC: demo-vpc

  • Subnets: private1-east-1a, private2-east-1b

  • Desired Capacity: 2

  • Max Capacity: 4

  • Load Balancer: ❌ (not added yet)

➑️ Result: Two EC2 instances are created inside private subnets with no public IPs.


πŸ” Step 4: Bastion Host for Private Access

Because our EC2s are in private subnets, we can't SSH into them directly. So we set up a bastion host.

βœ… Bastion Host EC2:

  • AMI: Ubuntu

  • Subnet: public1-east-1a

  • Security Group: Allow SSH (port 22) from anywhere

  • Key Pair: east1key

βœ… Copy east1key.pem to Bastion Host:

You can use scp or any file transfer tool.

scp -i east1key.pem east1key.pem ubuntu@<bastion-public-ip>:/home/ubuntu/
chmod 400 east1key.pem

βœ… SSH into Private EC2 from Bastion:

ssh -i east1key.pem ubuntu@<private-ec2-ip>

πŸ”’ Production Tip: Lock down EC2 port 8000 to the ALB's security group post-setup

Restrict Bastion’s SSH access to your IP in production


πŸ§ͺ Step 5: Deploy a Simple Web App

On one of the private EC2s, we’ll deploy a basic Python server:

βœ… Create index.html:

<!DOCTYPE html>
<html>
<body>
  <h1>My First AWS PROJECT to demonstrate apps in private subnet</h1>
</body>
</html>

βœ… Start the Python HTTP Server:

python3 -m http.server 8000

Only one EC2 serves this page; the other EC2 is left idle to simulate an unreachable server.


βš–οΈ Step 6: Application Load Balancer (ALB)

Now we expose our private EC2s to the internet using a Layer 7 ALB.

βœ… Create Target Group:

  • Name: aws-prod-example

  • Target Type: Instances

  • Protocol: HTTP

  • Port: 8000

  • VPC: demo-vpc

  • Register both EC2s

βœ… Create Load Balancer:

  • Type: Application Load Balancer

  • Scheme: Internet-facing

  • Subnets: Public subnets of the VPC

  • Security Group:

    • βœ… Allow port 80 (HTTP) from 0.0.0.0/0

βœ… Listener Rule:

  • Forward all HTTP traffic to aws-prod-example Target Group


πŸ” Security Group Summary

ComponentInbound RuleWhy?
ALBPort 80 from 0.0.0.0/0Accept HTTP from internet
EC2s (ASG)Port 8000 (from ALB only)Receive traffic from ALB
Bastion HostPort 22 from 0.0.0.0/0SSH access to reach private EC2s

πŸ’‘ Pro Tip: In production, lock down port 8000 to only allow the Load Balancer's security group.


βœ… Result

  • Visiting the DNS of the Load Balancer shows the HTML page.

  • 50% of requests fail (because only one EC2 is serving), simulating unbalanced load distribution.

  • This demonstrates how load balancing distributes traffic and the importance of app health in target groups.

  • πŸ’‘ ALB health checks would mark the idle instance as unhealthy, routing 100% traffic to the active instance.


πŸ“Œ Key Learnings

  • πŸ”’ Private EC2s are safe from public access, enhancing security.

  • πŸšͺ Bastion hosts allow secure admin access to private instances.

  • βš–οΈ Load balancers make private services accessible without exposing EC2s directly.

  • πŸ“ˆ Auto Scaling helps scale app servers up/down based on traffic.


🧠 Final Thoughts

This project is a great starting point for understanding real-world cloud architecture. You've practiced:

  • Networking (VPCs, subnets, security groups)

  • Auto Scaling

  • Bastion host setup

  • Load balancing

  • Web app deployment


🏒 Real-world analogy

Imagine a secure office building:

  • 🧍 Receptionist (ALB) accepts visitor requests at front desk (port 80)

  • πŸšͺ Receptionist walks to employee office (port 8000) with the request

  • πŸ‘©β€πŸ’Ό Employee sends response back through receptionist

  • πŸ›‘οΈ Visitors never enter employee offices directly


Thanks so much for reading! 😁
If you enjoyed this, feel free to like, share, or follow for more AWS/DevOps content.

0
Subscribe to my newsletter

Read articles from Ayush Shrotriya directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ayush Shrotriya
Ayush Shrotriya