Janus
Getting Started

AWS Deployment

Production deployment on AWS using Terraform with ECS Fargate, RDS, and ElastiCache.

The terraform/ directory contains production-ready AWS infrastructure. Everything is provisioned with a single terraform apply.

Simpler options

If you don't need AWS, you can deploy with Docker Compose, Coolify, or Render instead.

Architecture

AWS Deployment Architecture

ComponentServiceStagingProduction
ComputeECS Fargate0.5 vCPU, 1GB, 1 task1 vCPU, 2GB, 2-4 tasks
DatabaseRDS PostgreSQL 16db.t4g.micro, single-AZdb.t4g.small, Multi-AZ
CacheElastiCache Redis 7cache.t4g.microcache.t4g.small
Load BalancerALBHTTPS, ACM certHTTPS, ACM cert
CDNCloudFrontSDK from S3SDK from S3
DNSRoute 53root, api, sdk subdomainsroot, api, sdk subdomains
SecretsSecrets Managerauto-generatedauto-generated
LogsCloudWatchJSON structuredJSON structured
ImagesECR10-image retention10-image retention

ECS services auto-scale between 1 and 4 tasks based on CPU and memory utilization.

Prerequisites

  • Terraform >= 1.5
  • AWS CLI configured with credentials
  • A registered domain in Route 53 (or delegate NS records)

Deploy

cd terraform
terraform init

# Staging
terraform plan -var-file=environments/staging.tfvars
terraform apply -var-file=environments/staging.tfvars

# Production
terraform plan -var-file=environments/production.tfvars
terraform apply -var-file=environments/production.tfvars

Secrets (HMAC, JWT, cookie, auth) are auto-generated on first apply and stored in AWS Secrets Manager. They're injected into ECS task definitions as environment variables.

Environment files

staging.tfvars

environment       = "staging"
domain            = "staging.janus.example.com"
api_cpu           = 512
api_memory        = 1024
api_desired_count = 1
db_instance_class = "db.t4g.micro"
db_multi_az       = false
redis_node_type   = "cache.t4g.micro"

production.tfvars

environment       = "production"
domain            = "janus.example.com"
api_cpu           = 1024
api_memory        = 2048
api_desired_count = 2
db_instance_class = "db.t4g.small"
db_multi_az       = true
redis_node_type   = "cache.t4g.small"

Terraform resources

FileResources
main.tfProvider, VPC, subnets
ecs.tfECS cluster, task definitions, services, auto-scaling
rds.tfPostgreSQL RDS instance, subnet group, parameter group
elasticache.tfRedis cluster, subnet group
alb.tfApplication Load Balancer, target groups, listeners
cloudfront.tfCDN distribution for SDK delivery
route53.tfDNS records (root, api, sdk subdomains)
acm.tfSSL/TLS certificates
secrets.tfSecrets Manager for auto-generated secrets
security-groups.tfVPC security groups
outputs.tfALB DNS, CloudFront URL, RDS endpoint

CI/CD integration

The deploy.yml GitHub Actions workflow handles deployment automatically:

  1. Builds Docker images for API and Dashboard
  2. Pushes to ECR
  3. Updates ECS task definitions
  4. Uploads SDK to S3
  5. Invalidates CloudFront cache

AWS authentication uses OIDC with short-lived credentials — no long-lived access keys. Production deploys require manual approval via GitHub Environments.

Monitoring

  • Health checks: ALB health checks hit /health (liveness) and /ready (DB + Redis connectivity)
  • Logs: JSON structured logs in CloudWatch, queryable with Insights
  • Metrics: Prometheus endpoint at /metrics, scrapeable by CloudWatch agent or external Prometheus
  • Alerts: Configure CloudWatch Alarms on ECS CPU/memory, RDS connections, and Redis evictions

Cost estimate

ComponentStaging (monthly)Production (monthly)
ECS Fargate~$15~$60
RDS~$15~$30
ElastiCache~$12~$25
ALB~$16~$16
CloudFront~$1~$5
Route 53~$1~$1
Total~$60~$137

Costs vary by region and traffic. These estimates assume us-east-1 with moderate traffic.

Destroying infrastructure

terraform destroy -var-file=environments/staging.tfvars

This removes all resources including the database. Make sure to export any data before destroying.