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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ contracts/.stellar/
backend/data/
.current_bench.tmp
.bench_results.tmp
.terraform/
*.tfstate
*.tfstate.*
*.tfvars
!deployment/terraform/env/*.example

# Generated Soroban contract bindings are committed to the repository
# Regenerate with: CONTRACT_ID=$(cat contracts/contract_id.txt) npm run gen:bindings
Expand Down
25 changes: 25 additions & 0 deletions deployment/terraform/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions deployment/terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Terraform deployment

This directory contains a minimal AWS Terraform stack for Stellar Stream with separate staging and production workspaces.

## Layout

- `modules/vpc`: VPC, public/private subnets, NAT, routing
- `modules/ecs_backend`: ECS Fargate backend service behind an ALB
- `modules/frontend`: S3 static site behind CloudFront
- `modules/rds`: PostgreSQL RDS instance in private subnets

## Workspaces

Terraform workspaces are used to isolate staging and production:

```bash
cd deployment/terraform
terraform init
terraform workspace new staging
terraform workspace new production
terraform workspace select staging
terraform plan -var-file=env/staging.tfvars
terraform apply -var-file=env/staging.tfvars
```

## Secrets

Secrets are intentionally not stored in Terraform variables or state. Create the following values in AWS Secrets Manager before running Terraform:

- `stellar-stream/staging/jwt-secret`
- `stellar-stream/staging/admin-api-key`
- `stellar-stream/staging/webhook-signing-secret`
- `stellar-stream/production/jwt-secret`
- `stellar-stream/production/admin-api-key`
- `stellar-stream/production/webhook-signing-secret`

The RDS master password is managed by AWS RDS itself via `manage_master_user_password = true`, so no password is kept in state.

## Suggested variable files

Copy the example files into real environment files and replace the placeholders with your AWS values:

```bash
cp env/staging.tfvars.example env/staging.tfvars
cp env/production.tfvars.example env/production.tfvars
```

Then apply with the matching workspace.
10 changes: 10 additions & 0 deletions deployment/terraform/env/production.tfvars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
project_name = "stellar-stream"
environment = "production"
aws_region = "us-east-1"
frontend_bucket_name = "stellar-stream-production-frontend-0001"
backend_image = "123456789012.dkr.ecr.us-east-1.amazonaws.com/stellar-stream-backend:production"
backend_desired_count = 2
jwt_secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:stellar-stream/production/jwt-secret"
admin_api_key_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:stellar-stream/production/admin-api-key"
webhook_signing_secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:stellar-stream/production/webhook-signing-secret"
allowed_origins = ["https://app.example.com"]
10 changes: 10 additions & 0 deletions deployment/terraform/env/staging.tfvars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
project_name = "stellar-stream"
environment = "staging"
aws_region = "us-east-1"
frontend_bucket_name = "stellar-stream-staging-frontend-0001"
backend_image = "123456789012.dkr.ecr.us-east-1.amazonaws.com/stellar-stream-backend:staging"
backend_desired_count = 1
jwt_secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:stellar-stream/staging/jwt-secret"
admin_api_key_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:stellar-stream/staging/admin-api-key"
webhook_signing_secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:stellar-stream/staging/webhook-signing-secret"
allowed_origins = ["https://staging.example.com"]
66 changes: 66 additions & 0 deletions deployment/terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
data "aws_caller_identity" "current" {}

locals {
tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "Terraform"
}
}

module "vpc" {
source = "./modules/vpc"

project_name = var.project_name
environment = var.environment
vpc_cidr = var.vpc_cidr
public_subnet_cidrs = var.public_subnet_cidrs
private_subnet_cidrs = var.private_subnet_cidrs
availability_zones = ["${var.aws_region}a", "${var.aws_region}b"]
}

module "rds" {
source = "./modules/rds"

project_name = var.project_name
environment = var.environment
db_name = var.db_name
db_username = var.db_username
db_instance_class = var.db_instance_class
db_allocated_storage = var.db_allocated_storage
db_backup_retention_days = var.db_backup_retention_days
subnet_ids = module.vpc.private_subnet_ids
vpc_id = module.vpc.vpc_id
vpc_cidr = var.vpc_cidr
}

module "backend" {
source = "./modules/ecs_backend"

project_name = var.project_name
environment = var.environment
vpc_id = module.vpc.vpc_id
public_subnet_ids = module.vpc.public_subnet_ids
private_subnet_ids = module.vpc.private_subnet_ids
backend_image = var.backend_image
backend_cpu = var.backend_cpu
backend_memory = var.backend_memory
backend_desired_count = var.backend_desired_count
aws_region = var.aws_region
db_host = module.rds.db_host
db_port = module.rds.db_port
db_name = module.rds.db_name
db_user = module.rds.db_user
jwt_secret_arn = var.jwt_secret_arn
admin_api_key_arn = var.admin_api_key_arn
webhook_signing_secret_arn = var.webhook_signing_secret_arn
allowed_origins = var.allowed_origins
}

module "frontend" {
source = "./modules/frontend"

project_name = var.project_name
environment = var.environment
bucket_name = var.frontend_bucket_name
}
Loading