Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 123 additions & 44 deletions infra/terraform/README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,77 @@
# Brain Storm - Terraform Infrastructure

This directory contains Terraform configurations for deploying Brain Storm to AWS.
This directory contains Terraform configurations for deploying Brain Storm to AWS using infrastructure as code.

## Architecture

- VPC with public and private subnets across 2 availability zones
- RDS PostgreSQL 16 with automated backups
- ElastiCache Redis cluster with automatic failover
- ECS Fargate for container orchestration
- Application Load Balancer for traffic distribution
```
Internet
┌─────────────────────────────────────────────────────────┐
│ AWS Account │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ VPC (10.0.0.0/16) │ │
│ │ │ │
│ │ Public Subnets (AZ-a, AZ-b) │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ Application Load Balancer │ │ │
│ │ │ :80 (HTTP) → redirect or forward │ │ │
│ │ │ :443 (HTTPS, optional ACM cert) │ │ │
│ │ │ path /api/* → backend target group │ │ │
│ │ │ default → frontend target group │ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Private Subnets (AZ-a, AZ-b) │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ ECS Frontend │ │ ECS Backend │ │ │
│ │ │ (Fargate) │ │ (Fargate) │ │ │
│ │ │ Auto-scaling │ │ Auto-scaling│ │ │
│ │ └──────────────┘ └──────┬───────┘ │ │
│ │ │ │ │
│ │ ┌──────────────┐ ┌──────▼───────┐ │ │
│ │ │ ElastiCache │ │ RDS │ │ │
│ │ │ Redis 7.1 │ │ PostgreSQL │ │ │
│ │ │ (encrypted) │ │ 16.3 │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ECR repositories (backend + frontend) │
│ Secrets Manager (DB pwd, JWT, Stellar key) │
│ API Gateway (HTTP API + VPC Link) │
│ GitHub Actions OIDC role │
└─────────────────────────────────────────────────────────┘
```

## Modules

| Module | Purpose |
|--------|---------|
| `vpc` | VPC, subnets, NAT gateways, route tables, flow logs |
| `rds` | PostgreSQL 16 with enhanced monitoring, encrypted storage |
| `elasticache` | Redis 7.1 replication group with encryption |
| `ecs` | Fargate cluster, backend & frontend services, IAM roles |
| `alb` | Internet-facing ALB, path routing, optional HTTPS |
| `ecr` | Container registries with lifecycle policies |
| `autoscaling` | CPU/memory-based auto-scaling for ECS services |
| `api-gateway` | HTTP API Gateway with VPC Link and throttling |
| `oidc` | GitHub Actions keyless authentication |
| `secrets` | Secrets Manager for DB password, JWT, Stellar key |

## Prerequisites

- Terraform >= 1.0
- Terraform >= 1.5
- AWS CLI configured with appropriate credentials
- S3 bucket for remote state: `brain-storm-terraform-state`
- DynamoDB table for state locking: `brain-storm-terraform-locks`

## Setup Remote State
## Bootstrap Remote State

Run once before the first `terraform init`:

```bash
# Create S3 bucket for state
# Create S3 bucket with versioning and encryption
aws s3api create-bucket \
--bucket brain-storm-terraform-state \
--region us-east-1
Expand All @@ -29,7 +80,12 @@ aws s3api put-bucket-versioning \
--bucket brain-storm-terraform-state \
--versioning-configuration Status=Enabled

# Create DynamoDB table for locking
aws s3api put-bucket-encryption \
--bucket brain-storm-terraform-state \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'

# Create DynamoDB table for state locking
aws dynamodb create-table \
--table-name brain-storm-terraform-locks \
--attribute-definitions AttributeName=LockID,AttributeType=S \
Expand All @@ -40,54 +96,77 @@ aws dynamodb create-table \

## Usage

1. Copy the example variables file:
```bash
# 1. Copy and edit variables
cp terraform.tfvars.example terraform.tfvars
```
# Edit terraform.tfvars — never commit this file

2. Edit `terraform.tfvars` with your values
# 2. Provide sensitive values as environment variables (preferred)
export TF_VAR_db_password="$(openssl rand -hex 16)"
export TF_VAR_jwt_secret="$(openssl rand -hex 32)"
export TF_VAR_stellar_secret_key="your-stellar-key"

3. Initialize Terraform:
```bash
# 3. Initialize
terraform init
```

4. Plan the deployment:
```bash
terraform plan
```
# 4. Plan
terraform plan -out=tfplan

5. Apply the configuration:
```bash
terraform apply
# 5. Apply
terraform apply tfplan
```

## Outputs

After successful apply, Terraform will output:
- ALB DNS name for accessing the application
- VPC ID
- Database and Redis endpoints (sensitive)
| Output | Description |
|--------|-------------|
| `alb_dns_name` | ALB DNS name — point your domain here |
| `api_gateway_endpoint` | API Gateway URL — use as `api_base_url` in tfvars |
| `backend_repository_url` | ECR URL for backend images |
| `frontend_repository_url` | ECR URL for frontend images |
| `github_actions_role_arn` | Set as `AWS_ROLE_ARN` GitHub secret |
| `db_endpoint` | RDS endpoint (sensitive) |
| `redis_endpoint` | ElastiCache endpoint (sensitive) |

## Two-step bootstrap

On first apply, `backend_image` and `frontend_image` default to the ECR repos.
The ECR repos will be empty, so the ECS task definitions reference images that
don't exist yet. To bootstrap:

1. Run `terraform apply` — ECR repos, VPC, RDS, and Redis are created.
2. Build and push your images:
```bash
aws ecr get-login-password | docker login --username AWS \
--password-stdin $(terraform output -raw backend_repository_url | cut -d/ -f1)
docker build -t $(terraform output -raw backend_repository_url):latest apps/backend
docker push $(terraform output -raw backend_repository_url):latest
# repeat for frontend
```
3. Run `terraform apply` again — ECS services will start with the new images.

## HTTPS Setup

To enable HTTPS:

1. Request an ACM certificate in the same region as your ALB.
2. Set `https_certificate_arn` in `terraform.tfvars`.
3. Run `terraform apply` — the ALB will add an HTTPS listener and redirect HTTP.

## Resource Limits
## GitHub Actions OIDC

Production configuration uses:
- Backend: 512 CPU, 1024 MB memory (2 tasks)
- Frontend: 256 CPU, 512 MB memory (2 tasks)
- RDS: db.t3.micro with auto-scaling storage
- Redis: cache.t3.micro with 2 nodes
After `terraform apply`, add the `github_actions_role_arn` output as the `AWS_ROLE_ARN`
secret in your GitHub repository. Remove any existing `AWS_ACCESS_KEY_ID` /
`AWS_SECRET_ACCESS_KEY` secrets — the OIDC role replaces them.

## Cost Optimization

For development/staging environments, adjust in `terraform.tfvars`:
- Use smaller instance classes
- Reduce ECS task counts
- Disable multi-AZ for RDS and Redis
For dev/staging, adjust in `terraform.tfvars`:

## GitHub Actions OIDC

The `oidc` module provisions:
- An AWS IAM OIDC identity provider for `token.actions.githubusercontent.com`
- A least-privilege `GitHubActionsDeploymentRole` IAM role

After `terraform apply`, copy the `github_actions_role_arn` output and add it as the `AWS_ROLE_ARN` secret in your GitHub repository. Remove any existing `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` secrets.
```hcl
db_instance_class = "db.t3.micro"
rds_multi_az = false
redis_node_type = "cache.t3.micro"
backend_min_capacity = 1
frontend_min_capacity = 1
```
Loading
Loading