Deploy Runlayer on AWS ECS (Elastic Container Service) with Fargate using Terraform. This provides a serverless container deployment without managing Kubernetes clusters. Choose between minimal configuration (5 required parameters) or enterprise configuration (full customization).Infrastructure Repository:runlayer/runlayer-infra
This deployment creates AWS resources that incur costs. Typical costs range
from $100-400/month depending on configuration.
alb_access_type = "public" # "public" or "private"alb_allowed_cidrs = [ # Security group IPv4 ranges "0.0.0.0/0" # Internet (change for security) # "203.0.113.0/24", # Your office IPs # "198.51.100.0/24" # Your VPN IPs]alb_allowed_ipv6_cidrs = ["::/0"] # Security group IPv6 ranges (default: all)# WAF IP Allowlisting (recommended for production)waf_enable_ip_allowlisting = true # Enable WAF-based IP filteringwaf_allowlist_ipv4_cidrs = [ # Allowed IPv4 CIDR blocks "203.0.113.0/24", # Office network "198.51.100.42/32", # Specific IP address]waf_allowlist_ipv6_cidrs = [ # Allowed IPv6 CIDR blocks "2001:db8::/48", # Office IPv6 range]# SSL Certificate options (choose one):# Option 1: Look up existing wildcard certificate (DEFAULT)# Module derives wildcard from domain: ai.prod.yourcompany.com → *.prod.yourcompany.comhosted_zone_name = "prod.yourcompany.com" # Used for DNS records and certificate lookup# Option 2: Create new wildcard certificate with DNS validationenable_acm_dns_validation = true # Creates new cert instead of lookuphosted_zone_name = "prod.yourcompany.com" # Required for Route53 validation# Option 3: Use specific certificate ARN (bypasses module)ssl_certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/xxx"# DNS record control (separate from certificate management)create_dns_records = true # Creates Route53 ALIAS record pointing domain to ALB (default: false)
Dual ALB Setup (Split-Horizon DNS)
# Enable dual ALB for split-horizon DNS# Public ALB for internet traffic + Internal ALB for private network trafficenable_dual_alb = true# Optional: Use an existing private hosted zoneprivate_hosted_zone_id = "Z1234567890ABC"# Optional: Associate with a specific VPC (defaults to service VPC)private_hosted_zone_vpc_id = "vpc-1234567890abcdef0"# Optional: Associate with additional VPCs (for VPC peering scenarios)private_hosted_zone_additional_vpc_ids = [ "vpc-0987654321fedcba0", # Peered VPC 1 "vpc-1111222233334444", # Peered VPC 2]# Optional: Allow additional CIDRs to reach the internal ALB# Useful for VPN, Transit Gateway, or other private networks# that are not in the VPC or peered VPCsalb_internal_allowed_cidrs = [ "10.200.0.0/16", # Corporate VPN]alb_internal_allowed_ipv6_cidrs = [ "fd00::/64", # Internal IPv6 range]
Use Case:
Public access required (e.g., ChatGPT, external integrations)
Private network access for internal services (stays within VPC/peering)
Single domain name (runlayer.example.com) resolves differently based on network context
How it works:
Public DNS → Public ALB (internet traffic)
Private DNS → Internal ALB (VPC/peered traffic)
ECS services register with both ALBs
WAF applies only to public ALB
VPC Peering for Cross-VPC Connectivity
Security Note: VPC peering connections require peer_owner_id to be specified for all connections. This validation ensures you only accept connections from known and trusted AWS accounts. Connections are automatically accepted after validation.
Enable VPC peering to allow traffic between the Runlayer VPC and other VPCs (for example, a customer’s existing VPC or internal services VPC).
# Accept and configure VPC peering connectionsvpc_peering_connections = { "customer-vpc" = { peering_connection_id = "pcx-0abc123def456" # VPC peering connection ID from the initiating side peer_vpc_cidr = "172.16.0.0/16" # CIDR block of the peer VPC peer_owner_id = "123456789012" # AWS account ID of the peer (REQUIRED) peer_region = "us-east-1" # AWS region of the peer (optional) }}# Optional: For dual ALB setup, associate private hosted zone with peered VPCenable_dual_alb = trueprivate_hosted_zone_additional_vpc_ids = ["vpc-customer123"]
Security Features:
✅ Required peer validation - All connections must specify peer_owner_id
✅ Automatic acceptance after validation - Validation is the security control
✅ Automatic routing - Routes configured only for validated connections
✅ Security group integration - Backend allows traffic from validated peer CIDRs
Prerequisites:
The peer VPC must initiate the peering connection first
You need the peering connection ID (pcx-xxxxx)
You need the peer VPC’s CIDR block
You MUST provide the peer AWS account ID for security validation
Use Cases:
Connecting to a customer’s existing VPC for internal API access
Multi-VPC architectures with centralized services
Hybrid cloud setups with on-premises connectivity
VPC peering only works when the module creates the VPC (not with existing_vpc_id).
Service Scaling
services_configurations = { "backend" = { desired_count = 3 # Number of instances min_capacity = 2 # Min for auto-scaling max_capacity = 10 # Max for auto-scaling cpu = 2048 # CPU units (1024 = 1 vCPU) memory = 4096 # Memory in MB # Auto-scaling thresholds cpu_auto_scalling_target_value = 70 # Scale at 70% CPU memory_auto_scalling_target_value = 80 # Scale at 80% memory } "frontend" = { desired_count = 2 cpu = 512 memory = 1024 }}
# AWS CLIbrew install awscliaws configure# Terraformbrew install terraformterraform version
2
AWS Requirements
AWS account with sufficient permissions
Domain name you control (for DNS records and SSL)
Adequate service quotas (VPC, RDS, ECS)
By default, the module looks up an existing wildcard ACM certificate (e.g., *.staging.runlayer.com). If no wildcard certificate exists, set enable_acm_dns_validation = true to create one automatically with DNS validation.
3
SSL Certificate (Enterprise Only)
# Optional: Request certificate in ACMaws acm request-certificate \ --domain-name "*.yourcompany.com" \ --validation-method DNS \ --region us-east-1# Get Route53 hosted zone IDaws route53 list-hosted-zones-by-name \ --dns-name yourcompany.com
# Clone the infrastructure repositorygit clone https://github.com/runlayer/runlayer-infra.gitcd runlayer-infra# OR use the subtree in your main projectcd infra
# Secrets are automatically generated during deployment!# Database password and secret keys are created securely.# If you need to update any secrets after deployment:aws secretsmanager update-secret \ --secret-id "anysource-production-app-secrets-PROD2024" \ --secret-string '{ "CUSTOM_API_KEY": "your-custom-value" }'
# Check if wildcard certificate existsaws acm list-certificates --query "CertificateSummaryList[?contains(DomainName, '*')]"# The module derives: your-domain.example.com → *.example.com# Ensure a certificate exists for the wildcard domain
DNS validation fails (when enable_acm_dns_validation = true):
# Check certificate statusaws acm describe-certificate --certificate-arn your-cert-arn# Verify DNS records existdig _acme-challenge.your-domain.com CNAME
Application Not Accessible
Solution: Check security groups and target health:
# Check target group healthaws elbv2 describe-target-health --target-group-arn your-tg-arn# Check ECS service statusaws ecs describe-services --cluster anysource-production