βοΈ Day 28 of #90DaysOfCloud: Deploying a 3-Tier PHP Registration App on AWS with NGINX & RDS

Table of contents
- π§± What Is a 3-Tier Architecture?
- π₯οΈ Project Summary
- π§± Architecture Overview
- π§ Why 3-Tier Architecture?
- ποΈ Full Step-by-Step Setup Guide
- 1οΈβ£ Create VPC and Subnets
- VPC
- Subnets
- 2οΈβ£ Internet Gateway & Routing
- 3οΈβ£ Security Groups
- π Launch EC2 Instances
- Proxy Server (Public Subnet) β NGINX Reverse Proxy
- Install NGINX
- Configure NGINX as Reverse Proxy
- App Server (Private Subnet) β PHP Application
- Install Apache, PHP, and MySQL client
- Deploy PHP App Files
- Configure RDS Credentials (config.php)
- π’οΈ Amazon RDS (MariaDB)
- π Access the App
- π§Ό Cleanup (To Avoid Charges)
- πΈ Screenshots
- π‘ Best Practices and Improvements
- π§ Whatβs Next?

Today marks a milestone in my #90DaysOfCloud challenge, as I successfully built and deployed a 3-tier web application architecture on AWS, designed with best practices for security, modularity, and scalability. This blog details every major configuration β from VPC and subnets, through security controls, to the deployment of a PHP registration app β with NGINX as a reverse proxy and MariaDB RDS as persistent storage.
π§± What Is a 3-Tier Architecture?
A 3-tier architecture separates the application into:
Presentation Layer β NGINX Reverse Proxy (public subnet)
Application Layer β PHP App Server (private subnet)
Data Layer β Amazon RDS (private subnet)
This pattern improves security, scalability, and manageability.
π₯οΈ Project Summary
Component | AWS Resource | Subnet |
Reverse Proxy | NGINX on EC2 | Public Subnet |
App Server | PHP on EC2 | Private Subnet 1 |
Database | Amazon RDS (MariaDB) | Private Subnet 2 |
π§± Architecture Overview
A robust three-tier architecture separates presentation, application logic, and database into isolated network layers for improved security.
text Internet
β
βββββββββββββββ
β Proxy β β Public Subnet (10.0.1.0/24)
ββββββ¬βββββββββ
β (HTTP)
ββββββΌββββββ
β App EC2 β β Private Subnet (10.0.2.0/24)
ββββββ¬ββββββ
β (3306)
ββββββΌββββββ
β RDS β β Private Subnet (10.0.3.0/24)
ββββββββββββ
Presentation Layer: NGINX reverse proxy (public subnet)
Application Layer: PHP app (private subnet)
Database Layer: MariaDB on RDS (private subnet)
π§ Why 3-Tier Architecture?
Security: Only the proxy is exposed to the internet, the app and DB are shielded.
Scalability: Each layer can scale independently.
Maintainability: Easier to debug and maintain.
ποΈ Full Step-by-Step Setup Guide
1οΈβ£ Create VPC and Subnets
VPC
Name: 3TierVPC
IPv4 CIDR block: 10.0.0.0/16
Subnets
Public Subnet (Proxy) β 10.0.1.0/24
Private Subnet 1 (App) β 10.0.2.0/24
Private Subnet 2 (DB) β 10.0.3.0/24
2οΈβ£ Internet Gateway & Routing
Create IGW, attach to
3TierVPC
Public Route Table:
Destination: 0.0.0.0/0 β IGW
Associate with Public Subnet only
Private Route Table:
- No route to IGW (private only), used for both private subnets
3οΈβ£ Security Groups
Security Group | Inbound Rules | Outbound Rules |
Proxy SG | TCP 22 from <your-IP> |
TCP 80 from 0.0.0.0/0 | All allowed (default) |
| App SG | TCP 22 from <your-IP>
TCP 80 from Proxy SG | All allowed (default) |
| DB SG | TCP 3306 from App SG | All allowed (default) |
π Launch EC2 Instances
Proxy Server (Public Subnet) β NGINX Reverse Proxy
AMI: Amazon Linux 2
Install NGINX
sudo yum update -y
sudo amazon-linux-extras install nginx1 -y
sudo systemctl enable nginx
sudo systemctl start nginx
Configure NGINX as Reverse Proxy
Edit or create a new server block (/etc/nginx/conf.d/reverse-proxy.conf
):
textserver {
listen 80;
server_name _;
location / {
proxy_pass http://<App-Server-Private-IP>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Replace <App-Server-Private-IP>
with your actual app EC2 private IP.
Restart NGINX:
sudo systemctl restart nginx
App Server (Private Subnet) β PHP Application
AMI: Amazon Linux 2
Install Apache, PHP, and MySQL client
sudo yum update -y
sudo yum install -y httpd php php-mysqlnd mysql
sudo systemctl enable httpd
sudo systemctl start httpd
Deploy PHP App Files
Upload via SCP to the proxy, then to app server:
# Upload from your local machine to proxy
scp -i your-key.pem *.php ec2-user@<Proxy-Public-IP>:/home/ec2-user/
# SSH into app server (through the proxy, if needed), then:
sudo mv *.php /var/www/html/
Configure RDS Credentials (config.php
)
php<?php
$mysqli = new mysqli("your-rds-endpoint", "appuser", "password", "myappdb");
if ($mysqli->connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
?>
π’οΈ Amazon RDS (MariaDB)
Create DB Subnet Group: Add both private subnets for high availability
Launch RDS:
Engine: MariaDB
DB Name: myappdb
Username: appuser
Password: your_password
VPC: 3TierVPC
Subnet group: DB subnet group
Public access: No
Security group: DB SG
Once created, note the endpoint for your app serverβs config.
Create Table:
sqlmysql -h <rds-endpoint> -u appuser -p
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(50),
password VARCHAR(100)
);
π Access the App
Visit your proxy EC2βs public IP in a browser:
http://<Proxy-Public-IP>
You should see your PHP registration form, and registered users are now saved securely in Amazon RDS.
π§Ό Cleanup (To Avoid Charges)
Terminate EC2 instances
Delete RDS instance
Remove VPC and its resources
πΈ Screenshots
π‘ Best Practices and Improvements
Use SSL & enforce HTTPS: (Free cert with AWS ACM + NGINX config)
App Server Outbound Access: Add NAT Gateway if your app server requires outbound internet.
Secrets Management: Use AWS Secrets Manager for DB credentials, not hardcoded.
Backups & Availability: Enable automatic RDS backups and consider Multi-AZ deployment.
Monitoring: Use CloudWatch for logging and performance alerts.
π§ Whatβs Next?
Tomorrow, Iβll begin building a production-ready 3-tier architecture for a Java web application using Tomcat on AWS.
π§ The plan:
Set up NGINX as a reverse proxy in the public subnet
Deploy a Java app on Tomcat inside a private subnet
Connect to Amazon RDS as the backend database
π Iβll be sharing:
Step-by-step commands
All necessary configurations
Detailed architecture and networking setup
π₯ Stay tuned for a hands-on guide to deploying a secure and scalable Java web app on AWS from scratch!
Subscribe to my newsletter
Read articles from Pratik Das directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
