Historical only (August 2026). Terraform for the retired AWS ECS/RDS stacks. Production runs on R940; see
lastvet-gates/docs/deployment/R940_ENVIRONMENT_TOPOLOGY.md.
LastVet AWS infrastructure (Terraform)¶
Terraform for staging and prod API stacks on ECS Fargate + RDS Postgres 18 + EFS + ALB.
Dual URL is baked in:
lastvet-{env}/rds/master→MIGRATION_DATABASE_URLlastvet-{env}/rds/lastvet_app→DATABASE_APP_URL
Prerequisites¶
- AWS account with BAA accepted
- IAM access key + secret (not root)
- Tools:
terraform>= 1.5,awsCLI v2,node20+
- Export credentials in your shell (do not commit these):
One-shot apply (bootstrap + staging + prod)¶
Or per environment:
ECS desired_count defaults to 0 until an API image is pushed and app secrets are populated.
After Terraform apply¶
1. ACM DNS validation (Cloudflare)¶
cd infra/environments/staging && terraform output acm_validation_records
cd infra/environments/prod && terraform output acm_validation_records
Add the CNAME records in Cloudflare for each hostname (api-staging.last.vet, api.last.vet). HTTPS listener can be enabled after validation.
2. Point DNS at ALB (when ready)¶
| Hostname | Origin |
|---|---|
api-staging.last.vet |
staging ALB DNS name (terraform output alb_dns_name) |
api.last.vet |
prod ALB DNS name |
Cloudflare proxy is fine. Use Full (strict) once ACM is issued.
3. Database migrate + lastvet_app password¶
RDS is private. Run from a machine that can reach it (bastion, or temporarily allow your IP, or ECS one-off task).
Normal path (image contains migration files):
Or from ECS after --push-only:
Workaround (avoid): injecting migration SQL via a one-off ECS task when the running image does not include the new migrations/*.sql files. Acceptable only when Docker is unavailable; leaves schema ahead of code until ./infra/scripts/deploy-api-image.sh rollout. Never mark security guards verified until live API verify passes. Details: docs/deployment/DEV_STAGING.md § ECS SQL injection.
4. App secrets¶
Copy Railway env vars into lastvet-{env}/app in Secrets Manager before scaling ECS.
5. Build and deploy API image¶
# staging example
ECR_URL=$(cd infra/environments/staging && terraform output -raw ecr_repository_url)
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin "$ECR_URL"
docker build --platform linux/amd64 -t "$ECR_URL:latest" .
docker push "$ECR_URL:latest"
Update container_image in terraform.tfvars and set desired_count = 1, then terraform apply.
Layout¶
infra/
bootstrap/ # S3 state + DynamoDB lock (run once)
modules/
network/ # VPC, subnets, NAT, security groups
database/ # RDS + dual DB secrets
storage/ # EFS uploads volume
compute/ # ECR, ECS, ALB, ACM
stacks/api/ # Composes modules per environment
environments/
staging/
prod/
scripts/
Cost note¶
Each environment provisions VPC + NAT Gateway + RDS + ALB + EFS. Expect roughly $150–250/mo per environment at minimum sizes before traffic. Scale down by destroying staging when not in use.