Skip to main content

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 apply creates the entire stack from scratch with zero console clicks
  • terraform destroy removes everything cleanly, no orphaned resources
  • Changing aws_region and running terraform apply deploys to a new region
  • GitHub Actions runs terraform plan on every PR
  • GitHub Actions runs terraform apply on every merge to main
  • No secrets in code, .tf files, or git history
  • All resources tagged with Environment, Project, and ManagedBy = 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:

  1. Why S3 + DynamoDB for state? Not Terraform Cloud, open source, no external dependency
  2. Why Immutable deployment? No config drift, safest rollback strategy
  3. Why separate modules? Single responsibility, independent versioning, team ownership
  4. Why OIDC for GitHub Actions? No long-lived credentials, zero secret rotation
  5. 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