AWS EC2 RDS S3 Terraform

High-Availability AWS Web Application

Multi-AZ, auto-scaling application deployed on AWS with hardened EC2 instances, managed PostgreSQL with Multi-AZ failover, private S3 access via VPC Endpoint, and a WAF-protected ALB. Zero public ingress except through the load balancer.

VPC — 10.0.0.0/16 Availability Zone A Public — 10.0.1.0/24 Private — 10.0.3.0/24 Availability Zone B Public — 10.0.2.0/24 Private — 10.0.4.0/24 Internet Internet Gateway IGW · Highly Available Application Load Balancer HTTPS:443 · WAF · Layer 7 Web Server EC2 · t3.medium · AZ-A EC2 PostgreSQL Primary RDS · db.t3.large Multi-AZ · Encrypted RDS Web Server EC2 · t3.medium · AZ-B EC2 PostgreSQL Standby RDS · Multi-AZ Replica Auto-failover ~60–120s RDS Static Assets S3 VPC Endpoint sync replication VPC EP

Compute

Instance typet3.medium (2 vCPU, 4 GB RAM)
TenancyDefault VPC tenancy
AMIAmazon Linux 2023 (hardened)
Auto ScalingMin 2 / Max 8, target CPU 60%
IMDSv2Required — v1 disabled
EBS encryptionAES-256 (AWS-managed CMK)
Security groupIngress: ALB SG only, port 443. Egress: NAT GW

Database

EnginePostgreSQL 16.2
Instance classdb.t3.large (2 vCPU, 8 GB RAM)
Multi-AZEnabled — synchronous standby replica in AZ-B
Failover time~60–120 seconds
EncryptionAt-rest (AES-256) and in-transit (TLS 1.2+)
BackupsAutomated — 7-day retention, point-in-time recovery
Security groupIngress: EC2 SG only, port 5432. No public access

Load Balancer & WAF

TypeApplication Load Balancer (Layer 7)
ListenersHTTPS:443 only — HTTP:80 redirected
TLS policyELBSecurityPolicy-TLS13-1-2-2021-06
WAFAWS Managed Rules: AWSManagedRulesCommonRuleSet + SQLi
Access logsEnabled — S3 with 90-day retention
Deletion protectionEnabled

Storage & Networking

S3 bucketStatic assets — private, no public access block
S3 accessVPC Gateway Endpoint — traffic stays within AWS network
S3 encryptionSSE-S3 (AES-256)
VPC CIDR10.0.0.0/16 — /24 subnets per AZ per tier
Flow logsVPC Flow Logs to CloudWatch — 30-day retention
NAT GatewayOne per AZ for private subnet egress

Security Design Decisions

IMDSv2 Enforced on All Instances

IMDSv1 is trivially accessible from within an SSRF-vulnerable application — a single HTTP request to 169.254.169.254 returns credentials. IMDSv2 requires a session token obtained via a PUT request, which SSRF cannot perform in most configurations. All instances in this architecture set HttpTokens = required at the instance level, with an SCP enforcing this at the account level.

No Public Ingress to EC2 or RDS

EC2 security groups allow inbound traffic only from the ALB security group ID, not from a CIDR range. RDS security groups allow inbound only from the EC2 security group ID. This means there is no IP range that can be added to reach the database directly — the access path is ALB → EC2 → RDS only.

S3 via VPC Gateway Endpoint

S3 traffic from EC2 uses a VPC Gateway Endpoint rather than routing through the NAT Gateway or over the public internet. The bucket policy restricts access to requests originating from the VPC endpoint ID, so the bucket cannot be accessed from any other path — including from within AWS but outside the VPC.