This project provisions a production-grade three-tier WordPress architecture on AWS using Terraform, designed for high availability, security and scalability.
The infrastructure follows a layered design:
- CloudFront and WAF at the edge for global content delivery and request filtering
- An Application Load Balancer distributing traffic to EC2 instances in private subnets
- An Auto Scaling enabled application tier with shared file storage using EFS
- A highly available MySQL database managed by Amazon RDS within private subnets
- End-to-end HTTPS using AWS Certificate Manager with secure origin access
| Service | Purpose |
|---|---|
| Amazon CloudFront | CDN — caches static assets globally |
| AWS WAF | Filters malicious traffic, rate limiting |
| Amazon Route 53 | DNS management |
| Service | Purpose |
|---|---|
| Application Load Balancer | Distributes traffic across EC2 instances |
| AWS Certificate Manager | HTTPS certificates for ALB and CloudFront |
| Service | Purpose |
|---|---|
| EC2 Auto Scaling Group | Runs WordPress (Apache + PHP) |
| Amazon EFS | Shared wp-content across all instances |
| Service | Purpose |
|---|---|
| Amazon RDS MySQL | Managed database with automated backups |
| Service | Purpose |
|---|---|
| AWS IAM | Roles and policies — no static credentials |
| AWS Secrets Manager | RDS credentials management |
| Amazon CloudWatch | Metrics and WAF logging |
| AWS CloudTrail | Audit logging across all regions |
| Amazon S3 | Log storage (VPC, ALB, CloudFront, CloudTrail) |
- Modular Terraform design
- Multi-environment support (
dev/staging/prod) - Highly available — Multi-AZ subnets
- Auto Scaling EC2 instances
- Secure networking — private subnets for app and DB layers
- HTTPS enforced end-to-end (CloudFront → ALB → EC2)
- CDN acceleration via CloudFront
- WAF protection with managed rule sets
- Shared storage using EFS
- Managed RDS MySQL with Secrets Manager
- Full audit trail via CloudTrail
- No hardcoded secrets — all sensitive values via
terraform.tfvars(gitignored) - Private subnets for application and database layers
- Security groups with least privilege per layer
- HTTPS enforced — HTTP redirects to HTTPS at ALB
- CloudFront origin verification header — blocks direct ALB access
- WAF managed rules: IP reputation, anonymous IP, known bad inputs, common attacks, rate limiting
- IMDSv2 enforced on all EC2 instances
- EBS volumes encrypted at rest
- RDS storage encrypted at rest
- EFS encrypted at rest
- S3 log buckets encrypted and access-blocked
- IAM roles with least privilege — no static AWS credentials
.
├── env/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── terraform.tfvars.example
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── versions.tf
│ │ └── backend.tf
│ ├── staging/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── terraform.tfvars.example
│ │ ├── outputs.tf
│ │ ├── providers.tf
│ │ ├── versions.tf
│ │ └── backend.tf
│ └── prod/
│ ├── main.tf
│ ├── variables.tf
│ ├── terraform.tfvars.example
│ ├── outputs.tf
│ ├── providers.tf
│ ├── versions.tf
│ └── backend.tf
├── modules/
│ ├── naming/
│ ├── vpc/
│ ├── security_groups/
│ ├── alb/
│ ├── asg/
│ ├── efs/
│ ├── rds/
│ ├── iam/
│ ├── cloudfront/
│ ├── waf/
│ ├── acm_alb/
│ ├── acm_cloudfront/
│ ├── route53/
│ ├── logs/
│ └── cloudtrail/
├── user_data/
│ └── apache_php.sh.tpl
└── diagrams/
└── three-tier-architecture.png
- Terraform >= 1.10.0
- AWS CLI configured with appropriate permissions
- A registered domain in Route 53
- An S3 bucket for Terraform remote state
git clone https://github.com/kothetzawtun/terraform-aws-three-tier-wordpress.git
cd terraform-aws-three-tier-wordpresscd env/dev
cp terraform.tfvars.example terraform.tfvarsEdit terraform.tfvars with your values:
org = "your-org"
environment = "dev"
project = "wp"
aws_region = "ap-southeast-1"
cloudfront_domain_name = "dev.yourdomain.com"
cloudfront_hosted_zone_name = "yourdomain.com"
origin_verify_header_value = "your-secret-header-value"terraform initterraform planterraform applyAfter deployment, navigate to your configured domain. The WordPress setup page will load automatically.
WordPress stores uploads and plugins on disk. EFS provides shared storage across all EC2 instances in the Auto Scaling Group, ensuring all instances serve the same content.
Application and database layers are isolated in private subnets with no direct internet access. Only the ALB in public subnets accepts inbound traffic.
CloudFront caches static assets at edge locations globally, reducing latency and origin load. WAF filters malicious traffic before it reaches your infrastructure.
Each module encapsulates a single concern, making the codebase reusable, testable and easy to maintain across environments.
RDS master credentials are managed and auto-rotated by AWS Secrets Manager. No passwords are stored in code or environment variables.
| Component | HA Strategy |
|---|---|
| EC2 | Auto Scaling Group across 2 AZs |
| ALB | Spans 2 public subnets across 2 AZs |
| EFS | Mount targets in both private app subnets |
| RDS | Multi-AZ configurable via multi_az variable |
| NAT | Dual NAT Gateways (one per AZ) |
| CloudFront | Global edge network |
Estimated monthly costs for
ap-southeast-1. Actual costs vary based on traffic and data transfer.
| Service | Configuration | Est. Monthly Cost |
|---|---|---|
| EC2 (x2) | c7i.large x2 | ~$130 |
| RDS | db.m7i.large, Multi-AZ, 100GB gp3 | ~$230 |
| NAT Gateway (x2) | + data transfer | ~$130 |
| ALB | + LCU charges | ~$25 |
| CloudFront | PriceClass_All, moderate traffic | ~$20 |
| EFS | Bursting | ~$5 |
| WAF | 6 rules + Bot Control | ~$25 |
| S3 (logs) | 4 buckets | ~$5 |
| CloudTrail | Multi-region | ~$5 |
| Route53 | 1 hosted zone | ~$1 |
| Secrets Manager | 1 secret | ~$1 |
| ACM | Free | $0 |
| Total | ~$577/month |
NAT Gateways are the biggest cost driver (~23% of total). Consider adding VPC Endpoints for S3 and Secrets Manager to reduce data transfer costs.
| Service | Staging | Production |
|---|---|---|
| EC2 | t3.small x2 | c7i.large x2 |
| RDS | db.t3.micro, single-AZ | db.m7i.large, Multi-AZ |
| NAT Gateway | x1 | x2 |
| WAF Bot Control | No | Yes |
| CloudFront Price Class | PriceClass_100 | PriceClass_All |
| Deletion Protection | Yes | Yes |
| Multi-AZ RDS | No | Yes |
| ASG min/max | 1/2 | 2/2 |
| Skip Final Snapshot | Yes | No |
| Est. Monthly Cost | ~$130/month | ~$577/month |
- Add VPC Endpoints for S3 and Secrets Manager — reduces NAT Gateway data transfer charges
- Use single NAT Gateway for staging — saves ~$65/month
- Remove Bot Control WAF rule for staging — saves ~$10/month base
- Enable EFS Intelligent Tiering — moves infrequently accessed files to cheaper storage
- Use Graviton instances (
c7g,m7g,r7g) — ~20% cheaper, requires ARM-compatible software verification
Thet Zaw Tun Cloud Engineer | Cloud Infrastructure | AWS | Terraform
This project is licensed under the MIT License.
