AWS Deployment Guide¶
Use the AWS Terraform foundation when SkillMeat needs managed infrastructure or an AWS-hosted development environment.
For compute, storage, network, and external-service requirements by deployment method, see Deployment System Requirements.
Plan / Decision Matrix¶
| Mode | Use When | Infrastructure Shape |
|---|---|---|
dev-ec2 |
You want the fastest disposable AWS dev box with the same Compose profiles used locally. | One public EC2 instance running Docker Compose. Dependencies are co-located, and enterprise starts Postgres through Compose. |
dev-fargate |
You want cloud parity with ECS/Fargate behavior at low cost. | Public ECS web/API tasks, no NAT, one task each, tiny RDS, low log retention, deletion protection off. |
staging |
You need a managed pre-production environment. | Fargate web/API services, managed RDS PostgreSQL, Secrets Manager, CloudWatch Logs. |
production |
You need the managed production path. | Fargate web/API services, private RDS PostgreSQL, production retention/protection settings, Secrets Manager, CloudWatch Logs. |
The production and staging managed AWS path is Fargate plus RDS managed services. dev-fargate keeps that architecture but makes it disposable and low-cost. dev-ec2 is intentionally different: it is a single-box Compose deployment for development and profile testing, with public EC2 web/API URLs and optional SSH key or SSM access.
Layout¶
Terraform is expected under deploy/aws/terraform/:
deploy/aws/terraform/
├─ envs/
│ ├─ staging/
│ ├─ production/
│ ├─ dev-fargate/
│ └─ dev-ec2/
└─ modules/
├─ skillmeat_aws/
└─ skillmeat_ec2_dev/
The root Makefile wraps common Terraform commands so operators can use the same command shape for all environments.
Architecture¶
The managed Fargate environments provision this AWS shape for SkillMeat:
- Application Load Balancer routes public traffic to the web and API services.
- ECS Fargate runs separate
webandapitasks from GHCR-published images. - RDS PostgreSQL runs in private networking and is not publicly reachable.
- AWS Secrets Manager stores database credentials and application secrets for ECS task injection.
- CloudWatch Logs collects web and API task logs.
Users -> ALB -> ECS Fargate web
-> ECS Fargate API -> RDS PostgreSQL private subnet
-> Secrets Manager
-> CloudWatch Logs
dev-fargate uses the same skillmeat_aws module with development inputs: public ECS tasks, no NAT, one API task, one web task, tiny RDS, low retention, and deletion protection disabled.
dev-ec2 runs the existing Docker Compose deployment on one EC2 instance. It supports the local, local-auth, and enterprise Compose profiles. All dependencies run on the instance; in enterprise, Postgres starts through Compose instead of RDS. Use the public EC2 web/API URLs for access, and configure an SSH key or SSM if operator shell access is needed.
Image Configuration¶
Terraform consumes published GHCR image tags for the web and API containers. Publish images before planning or applying an environment update, then point the environment variables or Terraform inputs at the intended tags. Prefer immutable version tags over latest so task definition changes are explicit and reviewable.
Next.js inlines NEXT_PUBLIC_* values during pnpm build. Runtime ECS environment variables do not change client-side values already compiled into the web image. Build the web image with the correct public API URL, auth mode, and Clerk publishable key for the target environment before publishing the tag Terraform will deploy.
Local Commands¶
Set TF_ENV to dev-fargate, dev-ec2, staging, or production:
make terraform-fmt
make terraform-validate TF_ENV=dev-fargate
make terraform-plan TF_ENV=dev-ec2
make terraform-validate TF_ENV=staging
make terraform-plan TF_ENV=production
Shortcut targets:
make terraform-validate-staging
make terraform-validate-production
make terraform-validate-dev-fargate
make terraform-validate-dev-ec2
make terraform-plan-staging
make terraform-plan-production
make terraform-plan-dev-fargate
make terraform-plan-dev-ec2
terraform-fmt checks all Terraform files under deploy/aws/terraform. terraform-validate runs terraform init -backend=false before validation. terraform-plan uses the selected environment root and requires AWS credentials plus any configured remote backend access.
Usage Examples¶
Validate the disposable Fargate development environment:
Plan a single-box EC2 Compose environment:
For dev-ec2, set compose_profile = "local" for SQLite/no-auth, compose_profile = "local-auth" for SQLite with Clerk, or compose_profile = "enterprise" for Compose-managed PostgreSQL on the same instance. local-auth and enterprise require the relevant Clerk values in env_vars; enterprise should also set POSTGRES_PASSWORD in secret_env_vars so the Postgres container and API DATABASE_URL agree.
Use the generic target for any environment root:
CI Validation¶
.github/workflows/terraform.yml runs when files under deploy/aws/** change. It checks Terraform formatting, then validates the dev-fargate, dev-ec2, staging, and production environment roots with terraform init -backend=false. The workflow does not read secrets and does not run terraform plan or terraform apply.
Release Checklist¶
- Build and publish web/API images to GHCR with environment-appropriate values.
- Update the selected Terraform environment inputs to reference the new image tags.
- Run
make terraform-validate TF_ENV=<env>. - Run
make terraform-plan TF_ENV=<env>with AWS credentials. - Review the plan before applying through the approved operator workflow.