Final Project, Complete FinPay Infrastructure
Project Structure
finpay-infrastructure/
├── modules/
│ ├── networking/ (VPC, subnets, NAT, route tables)
│ ├── compute/ (Elastic Beanstalk / ECS, security groups)
│ ├── database/ (RDS, subnet group, parameter group)
│ ├── pipeline/ (ECR, CodeBuild, CodePipeline, IAM)
│ └── secrets/ (Secrets Manager, Parameter Store)
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ └── production/
│ ├── main.tf
│ ├── variables.tf
│ └── terraform.tfvars
├── bootstrap/ (S3 state bucket, DynamoDB lock table)
├── .github/
│ └── workflows/
│ └── terraform.yml (plan on PR, apply on merge)
└── .gitignore (*.tfstate, *.tfvars, .terraform/)
Acceptance Criteria
-
terraform applycreates the entire stack from scratch with zero console clicks -
terraform destroyremoves everything cleanly, no orphaned resources - Changing
aws_regionand runningterraform applydeploys to a new region - GitHub Actions runs
terraform planon every PR - GitHub Actions runs
terraform applyon every merge to main - No secrets in code,
.tffiles, or git history - All resources tagged with
Environment,Project, andManagedBy = terraform - State stored remotely in S3 with DynamoDB locking
Build Order
Follow this order when building from scratch:
1. bootstrap/ → creates S3 + DynamoDB for remote state
2. modules/networking → VPC, subnets, NAT gateways
3. modules/secrets → Secrets Manager, Parameter Store
4. modules/database → RDS (needs networking outputs)
5. modules/compute → Elastic Beanstalk/ECS (needs networking + secrets)
6. modules/pipeline → CodePipeline (needs compute + ECR)
7. environments/dev → calls all modules with dev tfvars
8. environments/production → calls all modules with prod tfvars
Key Design Decisions to Document
When you complete the project, write a README explaining:
- Why S3 + DynamoDB for state? Not Terraform Cloud, open source, no external dependency
- Why Immutable deployment? No config drift, safest rollback strategy
- Why separate modules? Single responsibility, independent versioning, team ownership
- Why OIDC for GitHub Actions? No long-lived credentials, zero secret rotation
- Why manage_master_user_password on RDS? Password never touches state
Completion Badge
When you can run this sequence without any errors:
# Clean slate
terraform destroy -auto-approve
# Full rebuild
terraform apply -auto-approve
# Change region
sed -i 's/us-east-1/eu-west-1/' terraform.tfvars
terraform apply -auto-approve
You are production-ready with Terraform.
Course version 1.0 · devopschronicles.com · Built alongside the FinPay API project