Production-style, multi-tier AWS architecture built with Terraform and optionally configured with Ansible. This project showcases end-to-end infrastructure automation: VPC networking, security hardening, load balancing, compute tiers, RDS, and S3 - plus app/web configuration via Ansible.
Why recruiters care
- Demonstrates real-world cloud architecture patterns (web/app/db tiers, ALB, private subnets, NAT).
- Uses Infrastructure as Code with clear variables, outputs, and reproducible setup.
- Adds configuration management for the web/app tiers using Ansible playbooks.
- Emphasizes security group scoping and tier isolation.
Tech stack
- Terraform
>= 1.0 - AWS provider
~> 5.0 - Ansible
2.9+(optional for post-provisioning)
What gets provisioned
- VPC with public and private subnets across two AZs
- Internet Gateway + NAT Gateway (single NAT in current implementation)
- ALB + target group + listener
- 2 Web EC2 instances (public subnets)
- 2 App EC2 instances (private subnets)
- RDS MySQL (Multi-AZ) in private DB subnets
- S3 bucket with public access blocked
Default region
ap-south-1(changeaws_regioninvariable.tfor viaterraform.tfvars)
Architecture at a glance
- Public Web Tier: ALB + EC2 web servers
- Private App Tier: EC2 app servers
- Private DB Tier: RDS MySQL (Multi-AZ)
- Strict security groups between tiers
- S3 for object storage (pr main Architecture diagram
Internet
|
v
ALB (public)
| \
| \
v v
Web EC2 #1 Web EC2 #2 (public subnets, AZ1/AZ2)
| |
v v
App EC2 #1 App EC2 #2 (private app subnets, AZ1/AZ2)
\ /
\ /
RDS MySQL (Multi-AZ, private DB subnets)
App EC2 -> NAT Gateway -> Internet (egress)
App EC2 -> S3 Bucket (pri
flowchart TB
Internet((Internet))
ALB[Application Load Balancer]
S3[(S3 Bucket)]
subgraph VPC
subgraph Public Subnets (AZ1/AZ2)
Web1[Web EC2 #1]
Web2[Web EC2 #2]
NAT[NAT Gateway]
end
subgraph Private App Subnets (AZ1/AZ2)
App1[App EC2 #1]
App2[App EC2 #2]
end
subgraph Private DB Subnets (AZ1/AZ2)
RDS[(RDS MySQL Multi-AZ)]
end
end
Internet --> ALB
ALB --> Web1
ALB --> Web2
Web1 --> App1
Web2 --> App2
App1 --> RDS
App2 --> RDS
App1 --> NAT
App2 --> NAT
App1 --> S3
App2 -->dev
Quick start
terraform init
terraform plan
terraform applyIf you want Ansible configuration after provisioning:
terraform output
sed -i 's/<WEB_1>/YOUR_WEB_1_IP/g' ansible/inventory.ini
sed -i 's/<WEB_2>/YOUR_WEB_2_IP/g' ansible/inventory.ini
sed -i 's/<APP_1>/YOUR_APP_1_IP/g' ansible/inventory.ini
sed -i 's/<APP_2>/YOUR_APP_2_IP/g' ansible/inventory.ini
ansible-playbook -i ansible/inventory.ini ansible/playbooks/site.ymlKey outputs
alb_dns_nameto access the web tierweb_serversandapp_serversinstance detailsrds_endpointfor database connectivity
Configuration
- Sensitive DB creds are marked
sensitiveinvariable.tf - Set
db_passwordand any overrides viaterraform.tfvarsor-var
Example:
db_password = "replace-me"
environment = "prod"Repository structure
main.tf # Core infrastructure (VPC, subnets, SGs, ALB, EC2, RDS, S3)
provider.tf # Provider and Terraform versions
variable.tf # Input variables and defaults
outputs.tf # Outputs for post-provisioning use
ansible/ # Playbooks and templates for web/app config
Security notes
- Web tier accepts HTTP/HTTPS from the internet via ALB
- App tier only accepts traffic from web tier SG
- DB tier only accepts MySQL from app tier SG
- S3 bucket has public access blocked
Cleanup
terraform destroySuggested improvements
- Add HTTPS with ACM + ALB listener on 443
- Replace hardcoded AMI ID with data source lookup
- Add autoscaling groups for web/app tiers
- Add dual NAT gateways (one per AZ) for higher availability
- Add VPC endpoint for S3 to avoid public internet routes
- Enable RDS backups and encryption at rest