Architecture Overview This project deploys the following AWS components:
VPC • Public and private subnets across multiple AZs • Internet Gateway • Separate route tables
RDS (PostgreSQL) • Private subnets only • Security-group-based access
Lambda • IAM least-privilege execution role • CloudWatch Logs
S3 + CloudFront • Private S3 bucket • CloudFront Origin Access Control (OAC)
Optional SPA routing support • Terraform Remote State • S3 backend • DynamoDB state locking
Repository Structure
terraform-blueprints/
├── environments/ │ ├── dev/ │ │ ├── backend.tf.example │ │ ├── main.tf │ │ ├── providers.tf │ │ ├── variables.tf │ │ ├── outputs.tf │ │ └── terraform.tfvars (ignored) │ ├── stage/ │ └── prod/ ├── modules/ │ ├── vpc/ │ ├── rds/ │ ├── lambda/ │ └── s3-cloudfront/ ├── lambda-dist/ │ └── hello.zip ├── .gitignore └── README.md
Design Principles • Modules are reusable All AWS resources live inside /modules. No resources are defined directly in environments.
• Environments only wire modules together
environments/dev shows how the same modules can be composed with different inputs.
• Remote state is required but not hardcoded
Each environment provides a backend.tf.example file instead of committing real backend credentials.
Terraform Backend (Remote State)
This project uses an S3 backend with DynamoDB locking.
To avoid hard-coding personal infrastructure into GitHub, the backend file is provided as a template.
Setup steps
-
Copy the backend template: cp environments/dev/backend.tf.example environments/dev/backend.tf
-
Edit backend.tf and replace: bucket = "YOUR_STATE_BUCKET" dynamodb_table = "YOUR_LOCK_TABLE"
-
Initialize Terraform: terraform init
The real backend.tf file is intentionally ignored by Git.
- MODULES
VPC Module Location: modules/vpc Creates: VPC with DNS support • Public & private subnets (AZ-mapped) • Internet Gateway • Public & private route tables
Outputs: • vpc_id • public_subnet_ids • private_subnet_ids
RDS Module Location: modules/rds Creates: • DB subnet group (private subnets) • RDS PostgreSQL instance • Dedicated DB security group
Security: • Database is not publicly accessible • Access allowed only via security group references
Outputs: • db_endpoint • db_port • db_security_group_id
Lambda Module Location: modules/lambda Creates:
IAM execution role • CloudWatch log group • Lambda function deployed from ZIP
Notes: • Uses filebase64sha256() to trigger updates on code change • Not attached to a VPC by default (simpler dev setup)
Outputs: • lambda_name • lambda_arn • lambda_role_arn
S3 + CloudFront Module Location: modules/s3-cloudfront Creates: • Private S3 bucket • CloudFront distribution • Origin Access Control (OAC) • Optional SPA routing support
Security: • Bucket blocks all public access • Only CloudFront can read objects
Outputs: • bucket_name • cloudfront_domain_name
Environments
The dev environment shows how modules are composed together: • VPC is created first • RDS is placed in private subnets • Lambda reads DB connection info via environment variables • CloudFront serves content from a private S3 bucket
Other environments (stage, prod) can reuse the same modules with different inputs.
Handling Secrets • Database credentials are passed via terraform.tfvars • terraform.tfvars is never committed • Sensitive variables are marked with sensitive = true