Skip to content

Terraform

All AWS infrastructure is defined as code using Terraform in the infra/terraform/ directory.


Directory Structure

infra/terraform/
    main.tf              # Root module - orchestrates all child modules
    variables.tf         # Root input variables
    outputs.tf           # Root outputs
    versions.tf          # Provider version constraints
    backend.tf           # State backend configuration (S3)
    backend-dev.hcl      # Dev backend config
    secrets.auto.tfvars  # Auto-loaded secret variables (gitignored)
    environments/        # Environment-specific variable files
        dev.tfvars
        staging.tfvars
        prod.tfvars
    modules/             # Reusable infrastructure modules
        alb/             # Application Load Balancer + WAF
        ecs/             # ECS Fargate cluster, services, ECR
        elasticache/     # ElastiCache (Valkey)
        iam/             # IAM roles, policies, OIDC provider
        rds/             # RDS PostgreSQL
        s3/              # S3 buckets with lifecycle policies
        secrets/         # AWS Secrets Manager
        vpc/             # VPC, subnets, NAT Gateway, route tables
    scripts/             # Deployment helper scripts

Module Inventory

Module Source Purpose
vpc ./modules/vpc VPC, 3-tier subnets, NAT Gateway, route tables
secrets ./modules/secrets Secrets Manager for DB password, API keys, JWT secrets
rds ./modules/rds PostgreSQL 16 with pgvector, automated backups
elasticache ./modules/elasticache Valkey (Redis-compatible) for caching and Celery broker
s3 ./modules/s3 Documents and media buckets with lifecycle policies
alb ./modules/alb Application Load Balancer, HTTPS, WAF
ecs ./modules/ecs Fargate cluster, API + Worker + Beat services, ECR
iam ./modules/iam Task roles, execution roles, GitHub Actions OIDC

Module Dependencies

flowchart TB
    VPC[vpc] --> RDS[rds]
    VPC --> EC[elasticache]
    VPC --> ALB[alb]
    VPC --> ECS[ecs]
    SEC[secrets] --> RDS
    SEC --> ECS
    ALB --> ECS
    RDS --> ECS
    EC --> ECS
    S3[s3] --> ECS
    ECS --> IAM[iam]
    SEC --> IAM

Key Variables

General

Variable Type Default Description
environment string Required dev, staging, or prod
project_name string carbon-connect Resource naming prefix
aws_region string eu-north-1 AWS region

Database (RDS)

Variable Type Default Description
db_instance_class string db.t4g.medium Instance type
db_allocated_storage number 50 Storage in GB
db_max_allocated_storage number 200 Auto-scale limit
db_multi_az bool false Multi-AZ for production
db_deletion_protection bool false Deletion protection
db_backup_retention_period number 7 Backup retention days

ECS

Variable Type Default Description
api_cpu number 1024 API container CPU units
api_memory number 2048 API container memory (MB)
api_desired_count number 2 Desired API tasks
api_min_count number 1 Min auto-scale
api_max_count number 10 Max auto-scale
worker_cpu number 1024 Worker container CPU
worker_memory number 2048 Worker container memory
use_fargate_spot bool true Use Spot for workers

Secrets (Sensitive)

Variable Type Description
claude_api_key string Anthropic API key
climatiq_api_key string Climatiq API key
meilisearch_master_key string Meilisearch master key
secret_key string Application session key
jwt_secret_key string JWT signing key

Secret Variables

Never commit secret values to version control. Use secrets.auto.tfvars (gitignored) or pass via environment variables.


State Backend

Terraform state is stored remotely in S3 with DynamoDB locking:

# backend.tf
terraform {
  backend "s3" {
    bucket         = "carbon-connect-terraform-state"
    key            = "terraform.tfstate"
    region         = "eu-north-1"
    encrypt        = true
    dynamodb_table = "carbon-connect-terraform-lock"
  }
}

How to Use

Initialize

cd infra/terraform

# Initialize with environment-specific backend
terraform init -backend-config=backend-dev.hcl

Plan

# Plan with environment variables
terraform plan -var-file=environments/dev.tfvars -out=plan.out

# Review the plan
terraform show plan.out

Apply

# Apply the plan
terraform apply plan.out

# Or apply directly (with confirmation prompt)
terraform apply -var-file=environments/dev.tfvars

Validate

# Check syntax
terraform validate

# Check formatting
terraform fmt -check -recursive

# Security scan
tfsec infra/terraform/

Destroy

# Destroy all resources (use with extreme caution)
terraform destroy -var-file=environments/dev.tfvars

Environment-Specific Configurations

  • Single NAT Gateway
  • db.t4g.medium RDS
  • Valkey Serverless
  • 1 API task, 1 Worker task
  • No Multi-AZ
  • No deletion protection
  • Single NAT Gateway
  • db.t4g.medium RDS
  • Valkey Serverless
  • 2 API tasks, 2 Worker tasks
  • No Multi-AZ
  • Deletion protection enabled
  • NAT Gateway per AZ
  • db.r6g.large RDS
  • Valkey with read replicas
  • 2-10 API tasks, 2-10 Worker tasks
  • Multi-AZ enabled
  • Deletion protection enabled
  • WAF enabled with rate limiting

CI/CD Integration

Terraform operations are integrated into GitHub Actions:

  1. Quality Gates workflow runs terraform validate and tfsec on every PR
  2. Deploy Staging triggers infrastructure updates on merge to staging
  3. Deploy Production requires manual approval with plan review

GitHub Actions uses OIDC federation (no long-lived AWS credentials):

module "iam" {
  source = "./modules/iam"
  create_oidc_provider = var.enable_github_oidc
  github_org           = "Carbon-Connect-Granted"
  github_repo          = "carbon-connect-vrci"
}