Skip to content

Repository files navigation

stdapi.ai - Terraform Module for AWS

Terraform Module OpenTofu Module

Deploy an OpenAI, Anthropic & Cohere compatible AI gateway on AWS. ECS Fargate infrastructure with auto-scaling, private subnets, KMS encryption and least-privilege IAM by default; HTTPS, WAF, API key authentication and CloudWatch alarms are opt-in inputs — see What this minimal configuration deploys and What gets provisioned, and when.

🌐 Documentation · 🚀 Start 14-Day Free Trial · 💻 GitHub Repository

Quick Start

Prerequisites

  1. Subscribe to stdapi.ai on AWS Marketplace (14-day free trial included)
  2. Install Terraform or OpenTofu >= 1.5 — see Requirements for exact version constraints
  3. Configure AWS credentials with IAM permissions to create VPC, ECS, ALB, S3, KMS, IAM, SQS, and CloudWatch resources

Deployable in any AWS region with ECS Fargate support.

Minimal Deployment

module "stdapi_ai" {
  source  = "stdapi-ai/stdapi-ai/aws"
  version = "~> 1.0"
}

What this minimal configuration deploys:

  • ECS Fargate service (auto-scaling, private subnets)
  • Dedicated VPC with private app subnets, NAT gateways for outbound AWS access, and the free S3 gateway endpoint
  • S3 bucket for generated and temporary files (KMS-encrypted)
  • IAM roles (least privilege) and CloudWatch logs

What it does NOT deploy (you add these explicitly for production):

  • ❌ No public endpoint — the service is only reachable from inside the VPC until you enable the ALB
  • ❌ No HTTPS / custom domain
  • ❌ No WAF
  • ❌ No API key authentication

Production-ready next step — add a public HTTPS endpoint with WAF and API key:

module "stdapi_ai" {
  source  = "stdapi-ai/stdapi-ai/aws"
  version = "~> 1.0"

  # Public HTTPS endpoint on a custom domain (ACM cert auto-issued via Route 53)
  alb_enabled           = true
  alb_public            = true
  alb_domain_name       = "api.example.com"
  alb_route53_zone_name = "example.com"

  # Protection
  alb_waf_enabled             = true
  alb_waf_rate_limit          = 2000
  alb_waf_block_anonymous_ips = true

  # Authentication — module generates a secure key and exposes it as a sensitive output
  api_key_create = true
}

For ready-to-deploy variants (single-region, EU/US multi-region, Open WebUI), see the samples repository. For deeper patterns (BYO VPC / ALB / Route 53 / S3, manual ECS, cost-optimized), see the advanced deployment guide.

License and Cost

stdapi.ai is dual-licensed: AGPL-3.0-or-later for the free community container image, or a commercial license obtained by subscribing on AWS Marketplace. This module is commercial-only by construction — it deploys the Marketplace ECR image, so an active Marketplace subscription is required. To run the AGPL community image instead, see the local deployment guide.

The Marketplace license is metered at $0.10 per container-hour, with a 14-day free trial on the license. autoscaling_min_capacity defaults to one task per availability zone and availability_zones_count defaults to all AZs in the region, so a default deployment in a 3-AZ region runs 3 tasks — about $216/month in license (720 h × $0.10 × 3), and about $432/month in a 6-AZ region such as us-east-1. Set availability_zones_count and autoscaling_min_capacity explicitly to control this.

Only the license is covered by the trial. AWS resources this module creates (Fargate, ALB, NAT gateways, KMS, CloudWatch, S3, SQS) and Amazon Bedrock inference are billed by AWS from the first hour, with no markup. Of those, the indexing queues are the one resource with no standing charge at all: Amazon SQS bills per request, an idle queue costs nothing, and indexing a file is a handful of requests. See the cost management guide and the licensing guide.

Module Features

Production-ready infrastructure following AWS Well-Architected Framework:

  • 🚀 Serverless Compute — ECS Fargate with intelligent auto-scaling (0.25-16 vCPU, CPU/Memory/Request-based)
  • ⚖️ Load Balancing — Application Load Balancer with HTTPS/TLS, configurable idle timeout for long operations
  • 🌐 Networking — Dedicated VPC with private app subnets; AWS access via NAT gateways or interface VPC endpoints; optional public subnets for the ALB; IPv4/IPv6 support
  • 🔒 Security — WAF with rate limiting & IP filtering, KMS encryption, IAM roles with least privilege
  • 📊 Monitoring — Container Insights dashboards, optional CloudWatch alarms, VPC Flow Logs, request/response logging
  • 💾 Storage — S3 buckets with encryption, versioning, lifecycle policies, multi-region support
  • 💰 Cost Optimization — Fargate Spot support (~70% discount), scheduled auto-scaling, resource right-sizing

Architecture

                        Internet
                           │  egress only when required (see table)
                ┌──────────▼──────────┐
                │   WAF    (optional) │   alb_waf_enabled
                └──────────┬──────────┘
                           │  inbound only when the ALB is enabled
                ┌──────────▼──────────┐
                │   ALB    (optional) │   alb_enabled / alb_public
                │   HTTPS / HTTP      │   (public subnets only if alb_public)
                └──────────┬──────────┘
                           │
   ┌───────────────────────┼───────────────────────┐
   │ VPC (dedicated, or bring-your-own subnet_ids) │
   │                       │                       │
   │            ┌──────────▼──────────┐  S3 gateway        ┌──────────────┐
   │            │     ECS Fargate     │  endpoint          │  S3 Bucket   │
   │            │   ┌─────────────┐   │  (always, free) ──▶│ (+ regional  │
   │            │   │  stdapi.ai  │   │                    │  buckets,    │
   │            │   │  Container  │   │                    │  KMS-encr.)  │
   │            │   └─────────────┘   │                    └──────────────┘
   │            │  app subnet (private)            │
   │            └──────────┬──────────┘            │
   │     egress to Bedrock, Polly, Transcribe, …   │
   │     uses exactly ONE of (mutually exclusive): │
   │       • NAT gateways            (default)     │
   │       • Interface VPC endpoints (no-internet) │
   └───────────────────────┬───────────────────────┘
                           │
                ┌──────────▼──────────┐
                │      CloudWatch     │
                └─────────────────────┘

What gets provisioned, and when

Component Created when
Dedicated VPC, private app subnets, ECS Fargate service, KMS-encrypted S3 bucket(s), S3 gateway endpoint, CloudWatch logs Always — except: passing your own subnet_ids skips VPC/subnet/endpoint creation entirely, and passing your own aws_s3_bucket skips bucket creation
NAT gateways (private internet egress) Default. Created whenever the app needs internet: AWS Marketplace auto-subscribe is on (aws_bedrock_marketplace_auto_subscribe, enabled unless explicitly set to false) or any AWS service runs outside the deployment region (e.g. multi-region aws_bedrock_regions). Set nat_gateways_allowed = false to instead make the app subnets public (cheaper, less isolated).
Interface VPC endpoints — Amazon Bedrock, Amazon Polly, Amazon Transcribe, Amazon Comprehend, Amazon Translate, CloudWatch Logs, SSM, ECR, Marketplace metering (Secrets Manager only with api_key_secretsmanager_secret, Amazon SQS only with the indexing queue in the deployment region) Only when the app needs no internet egress: aws_bedrock_marketplace_auto_subscribe = false and every AWS service is in the deployment region and vpc_endpoints_allowed = true (default). Replaces the NAT path — the two are never created together.
Public subnets Only with a public ALB (alb_enabled = true and alb_public = true)
ALB + HTTPS listener / ACM certificate alb_enabled = true (HTTPS when alb_domain_name / alb_certificate_arn is set; auto ACM + Route 53 via alb_domain_name). Without an ALB the service is only reachable from inside the VPC.
WAF (rate limiting, IP filtering) alb_waf_enabled = true (requires alb_enabled)
API key authentication One of api_key_create, api_key, api_key_ssm_parameter, api_key_secretsmanager_secret
Realtime API signing key (stored as an SSM parameter, like the API key) Generated when realtime_client_secret_key is unset and no API key is configured: the server otherwise signs the Realtime API ephemeral client secrets with a per-process random value that no other task can verify. Set realtime_client_secret_key to bring your own; with an API key configured, the server derives it from that key.
S3 vector bucket + its KMS key (Vector Stores API) aws_s3_vectors_bucket_create = true, or pass your own with aws_s3_vectors_bucket. Single-region (aws_s3_vectors_region, default the deployment region): a vector bucket is never handed to a model, so it needs no per-region twin. The API is disabled while neither is set.
Amazon SQS indexing queue + its dead-letter queue (durable vector store indexing) Default, but only once the Vector Stores API is enabled — there is nothing to index without it, and the server refuses the setting on its own. Makes an indexing job outlive the task that accepted it: whichever task is still running finishes it, so a deployment or a scale-in settles the file as completed instead of failed. Set aws_sqs_vector_store_queue_create = false to keep indexing inside the task that accepted the request, or pass your own standard queue with aws_sqs_vector_store_queue_url. Both queues are encrypted with the deployment's KMS key and carry no queue policy.
Amazon Bedrock batch service role (Batch API) aws_bedrock_batch_role_create = true, or pass your own with aws_bedrock_batch_role_arn. The API is disabled while neither is set.
CloudWatch alarms (error/critical logs) alarms_enabled = true
VPC Flow Logs vpc_flow_log_enabled (default true)

Examples & Integration

Ready-to-deploy Terraform examples live in the stdapi.ai samples repository:

Example What it deploys
getting_started_production Single-region production deployment with HTTPS, WAF, auto-scaling
getting_started_production_gdpr Multi-region EU deployment (4 regions) for GDPR data residency
getting_started_production_us Multi-region US deployment (3 regions) for high availability
getting_started_openwebui Full Open WebUI chat platform stack (Aurora + Valkey + SearXNG + stdapi.ai)

For integration against existing infrastructure and non-Terraform deployments, see the advanced deployment guide.

Documentation

Resource Description
Getting Started Deployment examples and first API call
Advanced Deployment VPC integration, multi-region, cost optimization
Configuration All environment variables and module parameters
API Reference OpenAI & Anthropic compatible API documentation
Use Cases Open WebUI, n8n, coding assistants, and more
Features Full product capabilities
Cost Management License metering, AWS resource costs, and per-request cost estimation
Resilience & Failover Multi-region routing, retry scope, and what does not fail over
Licensing AGPL-3.0 community edition vs the Marketplace commercial license
Compliance Data residency, region allow-lists, encryption, and outbound paths
IAM Permissions Task-role permissions the running gateway needs, for custom deployments and policy auditing

AWS Qualified Software

AWS Qualified Software badge

stdapi.ai is an AWS Qualified Software solution, verified against AWS technical and security requirements for AWS Marketplace.

Security Hub Controls

Controls are grouped below by the deployment feature that gates them, not by which internal module implements them — the baseline section always applies; the rest only come into play once you enable the corresponding input. Only controls whose resolution is worth calling out are listed; N/A controls for resource types this module never creates (EFS, Classic Load Balancers, ECS task sets, Windows containers, Route 53 hosted zones/health checks) are omitted entirely.

Severity: 🔴 Critical · 🟠 High · 🟡 Medium · 🔵 Low

Baseline (ECS Fargate, KMS keys, S3 buckets, IAM policies)

Always created, regardless of subnet_ids, alb_enabled, or any other toggle. Key inputs: tags = local.apn_tags (never null) is applied to every resource below, cloudwatch_logs_retention_in_days defaults 365, the main container sets read_only_root_filesystem = true and user = "65532:65532", secrets are passed via secrets never environment, and no security_group_rules_ingress/security_group_connect_ingress (internal wiring — not module variables) is passed (the only extra ingress rule references the ALB's security group, never a CIDR).

Control Severity Title Status Notes
KMS.1 / KMS.2 🟡 Medium IAM policies/inline policies should not allow decryption on all KMS keys ✅ Pass The application is only ever allowed to decrypt data using the specific encryption keys this deployment creates or is given — never every key in the account.
KMS.3 🔴 Critical KMS keys should not be deleted unintentionally ✅ Pass No deletion_window_in_days override — AWS's 30-day maximum applies.
KMS.4 🟡 Medium KMS key rotation should be enabled ✅ Pass Hardcoded for every key, including the per-Bedrock-region ones.
KMS.5 🔴 Critical KMS keys should not be publicly accessible ✅ Pass Every policy statement scopes a specific AWS service principal with an ArnLike/StringEquals condition — none is a wildcard principal.
ECS.3 / ECS.4 / ECS.9 / ECS.10 / ECS.17 / ECS.18 🟠 High / 🟡 Medium Various ECS controls (host PID namespace, non-privileged, logging config, Fargate platform version, host network mode, EFS in-transit encryption) ✅ Pass Unconditional defaults — not overridden.
ECS.14 🔵 Low ECS clusters should be tagged ✅ Pass The cluster always receives a Name tag regardless of tags.
ECS.5 🟠 High Task definitions should use read-only root filesystems ✅ Pass read_only_root_filesystem = true on the main container.
ECS.8 🟠 High Secrets should not be passed as container environment variables ✅ Pass The API key is passed via secrets.
ECS.12 🟡 Medium ECS clusters should use Container Insights ✅ Pass Defaults to "enabled".
ECS.13 / ECS.15 🔵 Low Service / task definition should be tagged ✅ Pass Non-null tags is applied directly, with no fallback.
ECS.20 🟡 Medium Task definitions should configure non-root users for Linux containers ✅ Pass user = "65532:65532", matching the Chainguard python:latest base image's actual default non-root user (nonroot, uid/gid 65532).
EC2.13 / EC2.14 / EC2.18 / EC2.53 / EC2.54 🟠 High ECS service security group should not allow unrestricted/admin-port ingress ✅ Pass No CIDR-based ingress rule exists.
EC2.19 🔴 Critical ECS service security group should not allow unrestricted access to high-risk ports ✅ Pass Same reasoning as above.
EC2.43 🔵 Low ECS service security group should be tagged ✅ Pass Unconditional.
CloudWatch.16 🟡 Medium CloudWatch log groups should be retained for a specified time period ✅ Pass cloudwatch_logs_retention_in_days defaults 365, applied to every ECS log group including Container Insights.
CloudWatch.17 🟠 High CloudWatch alarm actions should be activated ✅ Pass Unconditional whenever alarms exist (see Other options below).
IAM.1 🟠 High IAM policies should not allow full "*" administrative privileges ✅ Pass The ECS execution/task role policies and the two aggregated policies, aws_iam_policy.server and aws_iam_policy.server_services, use no wildcard actions.
IAM.21 🔵 Low IAM customer managed policies should not allow wildcard actions for services ✅ Pass Same statements as IAM.1 — no wildcard (service:*) actions.
S3.2 / S3.3 🔴 Critical S3 buckets should block public read/write access ✅ Pass aws_s3_bucket_public_access_block sets all four flags to true for every bucket (main and regional).
S3.8 🟠 High S3 buckets should block public access (account/bucket combined check) ✅ Pass Same configuration as S3.2/S3.3.
S3.5 🟡 Medium S3 buckets should require requests to use SSL ✅ Pass Bucket policy denies all s3:* actions when aws:SecureTransport is false.
S3.6 🟠 High S3 bucket policies should restrict access to other AWS accounts ✅ Pass The only statement is the TLS-enforcement Deny; no cross-account Allow.
S3.9 🟡 Medium S3 buckets should have server access logging enabled ⚠️ Pass on the data buckets, ❌ fail on the logs buckets The main bucket logs to a shared SSE-S3-encrypted logs bucket (also used for ALB access logs); each regional bucket logs to its own per-Region logs bucket, since S3 access log destinations must stay in the source bucket's Region. The logs buckets themselves have no destination: pointing one at itself is refused by S3, and pointing two at each other makes each delivery generate another.
S3.10 / S3.13 🟡 Medium / 🔵 Low S3 buckets should have lifecycle configurations ✅ Pass Every bucket gets an unconditional lifecycle configuration (tmp cleanup, files expiration, intelligent-tiering).
S3.11 🟡 Medium S3 buckets should have event notifications enabled ✅ Pass eventbridge = true is set unconditionally — zero-config, no targets/rules required.
S3.12 🟡 Medium ACLs should not be used to manage access to S3 buckets ✅ Pass New buckets default to BucketOwnerEnforced (ACLs disabled).
S3.14 🔵 Low S3 buckets should have versioning enabled ✅ Pass status = "Enabled" unconditionally on every bucket.
S3.15 🟡 Medium S3 buckets should have Object Lock enabled ⬜ N/A Object Lock (WORM immutability) doesn't fit this bucket's purpose — it's temporary storage with active expiration rules (1-day tmp cleanup, 30-day Files API expiration), the opposite of what Object Lock is for.
S3.17 🟡 Medium S3 buckets should be encrypted at rest with AWS KMS keys ⚠️ Pass on the data buckets, ❌ fail on the logs buckets SSE-KMS with a dedicated customer-managed key, bucket_key_enabled = true. The logs buckets are SSE-S3: S3 server access logging and ALB access logging both refuse a customer-managed key as their destination, so this is the strongest encryption those buckets can carry.
S3.20 🔵 Low S3 buckets should have MFA delete enabled ⬜ N/A (exempt) AWS's own control text exempts buckets with a lifecycle configuration — every bucket here always has one.
S3.22 / S3.23 🟡 Medium S3 buckets should log object-level read/write events ⬜ N/A Account-level control requiring an org-wide multi-Region CloudTrail trail — outside this module's scope.

Thanks to tags always being non-null, ECS.13/ECS.15 (tagged, above) actually pass — leaving tags unset would fail them; ECS.20 also passes thanks to the explicit user.

Dedicated VPC (default; skipped entirely when you pass your own subnet_ids)

Key inputs: flow-log retention follows cloudwatch_logs_retention_in_days (default 365); internet access is enabled by default (internal wiring — driven by aws_bedrock_marketplace_auto_subscribe, whose auto-subscribe default requires internet access for the AWS Marketplace API, and by any cross-region service usage); nat_gateways_allowed defaults true; the interface endpoint set (internal wiring — not a module variable) always includes s3, ssm, logs, ecr.api, ecr.dkr.

Control Severity Title Status Notes
EC2.2 🟠 High VPC default security groups should restrict all traffic ✅ Pass Unconditional.
EC2.6 🟡 Medium VPC flow logging should be enabled in all VPCs ✅ Pass vpc_flow_log_enabled defaults true.
EC2.21 🟡 Medium Network ACLs should not allow ingress from 0.0.0.0/0 to port 22/3389 ❌ Fail (accepted) The stateless network ACLs allow the ephemeral range for return traffic, which spans 3389. Unreachable: the security groups admit only 80/443 from the CIDRs you name, then only port 8000 from the load balancer. Details.
EC2.53 / EC2.54 / EC2.13 / EC2.14 🟠 High VPC default security group should not allow ingress from 0.0.0.0/0 to remote administration ports ✅ Pass Unconditional.
EC2.12 🔵 Low Unused EIPs should be removed ✅ Pass Unconditional.
EC2.37 / EC2.39 / EC2.40 / EC2.41 / EC2.42 / EC2.43 / EC2.44 / EC2.46 / EC2.174 🔵 Low Various VPC resources should be tagged ✅ Pass A Name tag is always merged in regardless of tags.
EC2.48 🔵 Low VPC flow logs should be tagged ✅ Pass Non-null tags is applied directly, with no fallback.
IAM.24 🔵 Low IAM roles should be tagged ✅ Pass Same reasoning as EC2.48, for the flow log's IAM role.
CloudWatch.16 🟡 Medium CloudWatch log groups should be retained for a specified time period ✅ Pass Flow-log retention follows cloudwatch_logs_retention_in_days (default 365).

Sub-variant — NAT gateways (default) vs. VPC interface endpoints (no internet egress)

Control Severity Title Status Notes
EC2.15 🟡 Medium EC2 subnets should not automatically assign public IP addresses ✅ Pass No subnet assigns addresses on launch, in either architecture. With nat_gateways_allowed = false the app subnets become public, but the task still takes its address from assign_public_ip on its own network configuration rather than from the subnet.
ECS.2 🟠 High Services should not have public IP addresses assigned automatically ✅ Pass by default Same trigger as EC2.15 — the ECS service only gets a public IP when nat_gateways_allowed = false.

Sub-variant — compliance VPC endpoints (compliance_vpc_endpoints_enabled = true)

Control Severity Title Status Notes
EC2.55 / EC2.56 / EC2.57 / EC2.58 / EC2.60 🟡 Medium VPC should be configured with an interface endpoint for ECR API / Docker Registry / SSM / SSM Incident Manager Contacts / SSM Incident Manager ⚠️ Conditional (default: ❌ Fail) The endpoint set (internal wiring vpc_endpoints_services) already requests ecr.api/ecr.dkr/ssm, but that only takes effect when there's no direct internet route — and by default there is one. Set compliance_vpc_endpoints_enabled = true to force these 5 endpoints regardless of internet posture.

Thanks to tags always being non-null, EC2.48 and IAM.24 (tagged, above) actually pass — leaving tags unset would fail them. One gap remains at default settings: EC2.55/56/57/58/60 are silently ineffective, because internet access is required for AWS Marketplace auto-subscribe — set compliance_vpc_endpoints_enabled = true to close it.

Public/HTTPS ALB (alb_enabled = true)

Control Severity Title Status Notes
ELB.1 🟡 Medium ALB should redirect all HTTP requests to HTTPS ⚠️ Conditional (default: ❌ Fail) The HTTP listener only redirects when a certificate exists. Set alb_certificate_arn or alb_domain_name (with a resolvable Route 53 zone) to get a certificate and enable the redirect.
ELB.4 🟡 Medium ALB should be configured to drop invalid HTTP headers ✅ Pass drop_invalid_header_fields = true is hardcoded.
ELB.5 🟡 Medium ALB should have logging enabled ⚠️ Conditional (default: ✅ Pass) alb_access_logging_enabled defaults true — a dedicated SSE-S3-encrypted bucket is created and wired to the load balancer's access_logs block.
ELB.6 🟡 Medium ALB should have deletion protection enabled ⚠️ Conditional (default: ❌ Fail) Set deletion_protection = true (default false).
ELB.12 🟡 Medium ALB should use defensive or strictest desync mitigation mode ✅ Pass Not set explicitly, but AWS's own default (defensive) satisfies the control.
ELB.13 🟡 Medium ALB should span multiple Availability Zones ⚠️ Conditional (default: ✅ Pass) Subnets use all available AZs by default (availability_zones_count = null) — always ≥2 in practice. Fails only if availability_zones_count is explicitly set to 1.
ELB.17 🟡 Medium ALB listeners should use recommended security policies ⚠️ Conditional (default: ✅ Pass once HTTPS exists, N/A otherwise) alb_ssl_policy defaults to ELBSecurityPolicy-TLS13-1-2-Res-PQ-2025-09, one of AWS's recommended policies. Only applies once the HTTPS listener exists (see ELB.1).
ELB.18 🟡 Medium ALB listeners should be configured with a secure listener protocol ❌ Fail The HTTP listener (port 80) always exists; there's no exemption for a redirect-only listener. Inherent to offering both HTTP and HTTPS.
ELB.21 🟡 Medium ELB target groups should have health check configured with encrypted protocol ❌ Fail The health check uses the default HTTP protocol; no variable exposes HTTPS health checks. Requires a code change to pass.
ELB.22 🟡 Medium ELB target groups should use encrypted transport protocol ❌ Fail The target group forwards to the ECS task over plain HTTP on the container port (TLS terminates at the ALB, not re-established to the backend). Requires a code change to pass.
ACM.1 🟡 Medium ACM certificates should be renewed after a specified time period ✅ Pass DNS validation (validation_method = "DNS"), which ACM renews automatically.
ACM.2 🟠 High RSA certificates managed by ACM should use a key length of at least 2,048 bits ✅ Pass key_algorithm isn't set, so ACM uses its default RSA_2048.
ACM.3 🔵 Low ACM certificates should be tagged ✅ Pass Tagged via non-null tags plus a Name tag.

Sub-variant — WAF (alb_waf_enabled = true, requires alb_enabled = true)

Control Severity Title Status Notes
ELB.16 🟡 Medium ALB should be associated with a WAF web ACL ⚠️ Conditional (default: ❌ Fail) Set alb_waf_enabled = true to pass.
WAFV2.1 (AWS WAF WAF.10) 🟡 Medium AWS WAF web ACLs should have at least one rule or rule group ✅ Pass once enabled Three AWS managed rule groups are always attached — never empty.
WAFV2.2 (AWS WAF WAF.11) 🔵 Low AWS WAF web ACL logging should be enabled ✅ Pass once enabled alb_waf_logging_enabled defaults true.

With alb_enabled = false (default), none of the ALB/WAF/ACM controls above apply — no load balancer exists. Once enabled, ELB.4 and ELB.5 pass out of the box. ELB.18, ELB.21, ELB.22 fail unconditionally — closing them requires re-architecting to terminate TLS on the backend, not just adding a variable — while ELB.1, ELB.6, ELB.16 fail by default until their respective variables are set.

Client IP trust (X-Forwarded-For) — not a Security Hub control, but a hardening applied automatically for ALB deployments. When the ALB is enabled together with log_client_ip = true, the module enables ENABLE_PROXY_HEADERS so the real client IP (not the ALB's) is recorded in request logs and OpenTelemetry spans. To keep that value trustworthy, it also pins PROXY_TRUSTED_HOSTS to the ALB's own subnet CIDRs (IPv4 and IPv6): the server honors X-Forwarded-* only when the immediate peer is the ALB. Because an ALB appends to X-Forwarded-For rather than replacing it, without this restriction a client could prepend a forged entry and poison the recorded client IP; pinning the trust to the ALB subnets makes the real appended address authoritative instead. This is defense in depth on top of the ECS security group, which already allows ingress only from the ALB's security group. Set proxy_trusted_hosts explicitly to override — for example when fronting the ALB with an additional proxy such as CloudFront, set it to that proxy's egress range. On an IPv6-enabled VPC the container binds a dual-stack socket (GRANIAN_HOST=::, needed because service discovery publishes an AAAA record per task), and the kernel then reports an IPv4 peer in IPv4-mapped form such as ::ffff:10.0.1.5, which belongs to no IPv4 network. The module therefore adds the matching ::ffff: range for every IPv4 entry — including entries you set through proxy_trusted_hosts yourself — so the ALB stays trusted. Write entries in their natural address family and let the module handle the mapping; a hand-rolled PROXY_TRUSTED_HOSTS on a dual-stack listener must cover both forms itself.

Other options

Independent toggles that don't gate other controls and aren't required to pass any control above.

CloudWatch Alarms (alarms_enabled = true, notifications sent to sns_topic_arn)

Control Severity Title Status Notes
CloudWatch.15 🟠 High CloudWatch alarms should have specified actions configured ⚠️ Conditional (default: N/A — no alarms) alarms_enabled defaults false. Set alarms_enabled = true and sns_topic_arn to pass.

Enabling it creates five alarms:

  • High memory usage — ECS service MemoryUtilization > 90% for 4 of 5 one-minute periods.
  • Unhealthy containers — ECS service HealthCheckFailed > 0.
  • CPU anomaly detection — CloudWatch anomaly-detection band around CPUUtilization; fires when usage exceeds the expected upper bound.
  • Max autoscaling capacity reached — Container Insights DesiredTaskCount >= autoscaling_max_capacity (only created if min/max capacity differ and Container Insights is enabled).
  • Application error/critical logs — a log metric filter counts error/ERROR/critical/CRITICAL matches in the app's CloudWatch log group; fires when any appear within a 60-second period.

The four ECS-level alarms require sns_topic_arn to be set (they always attach it as an action); the log-based alarm tolerates a null sns_topic_arn and simply exists without notifying anyone.

Durable vector store indexing (aws_sqs_vector_store_queue_create = true, the default, effective once the Vector Stores API is enabled)

Two queues are created — the indexing queue and its dead-letter queue — and both are treated identically: a dead-letter queue is a queue, and every control below is evaluated on each of them.

Control Severity Title Status Notes
SQS.1 🟡 Medium Amazon SQS queues should be encrypted at rest ✅ Pass kms_master_key_id is set to the deployment's customer-managed key on both queues, so each is SSE-KMS. The control accepts SSE-SQS too; the CMK is used to match the encryption posture of every other resource here.
SQS.2 🔵 Low SQS queues should be tagged ✅ Pass Both queues get the non-null tags plus a Name tag, so a tag key always exists. Fails only if you configure requiredTagKeys with keys this module does not set.
SQS.3 🔴 Critical SQS queue access policies should not allow public access ✅ Pass Neither queue has an access policy at all: the task role reaches the queue through its identity policy, scoped to that one queue ARN. A control that inspects the resource policy cannot find a wildcard principal where there is no resource policy.

The dead-letter queue additionally carries a RedriveAllowPolicy restricted to this deployment's own queue (redrivePermission = "byQueue"), so no other queue in the account can redrive into it. That is not a Security Hub control — left unset, Amazon SQS would allow every queue of the account.

Amazon GuardDuty Runtime Monitoring endpoint (guardduty_vpc_endpoint_enabled = true, dedicated VPC only) — not a Security Hub control. Enforced regardless of internet posture.

Route 53 Resolver DNS Firewall (dns_firewall_enabled = true, dedicated VPC only) — not a Security Hub control. Blocks/alerts on DNS queries to known-malicious domains (AWS Managed Domain Lists, plus DGA/DNS-tunneling detection via dns_firewall_advanced_enabled). Complements application-level SSRF protection against malicious-URL injection through user-supplied URL/file reference fields. Has no effect (and cannot be enabled) when subnet_ids is set.

All the options above are off by default and never required to pass a control in the sections higher up.


Terraform Documentation

Requirements

Name Version
terraform >= 1.5.0
aws >= 6.27.0
random >= 3.0.0

Providers

Name Version
aws >= 6.27.0
random >= 3.0.0

Modules

Name Source Version
kms_key JGoutin/kms-key/aws ~> 1.2
regional_kms JGoutin/kms-key/aws ~> 1.2
server JGoutin/ecs-fargate/aws ~> 1.4
vectors_kms JGoutin/kms-key/aws ~> 1.2
vpc JGoutin/vpc/aws ~> 1.4

Resources

Name Type
aws_acm_certificate.main resource
aws_acm_certificate_validation.main resource
aws_cloudwatch_log_group.waf resource
aws_cloudwatch_log_metric_filter.error_critical_logs resource
aws_cloudwatch_metric_alarm.error_critical_logs resource
aws_cloudwatch_query_definition.main resource
aws_iam_policy.server resource
aws_iam_policy.server_services resource
aws_iam_role.batch resource
aws_iam_role_policy.batch resource
aws_lb.main resource
aws_lb_listener.http resource
aws_lb_listener.https resource
aws_lb_target_group.main resource
aws_route53_record.acm_validation resource
aws_route53_record.main resource
aws_route53_record.main_ipv6 resource
aws_s3_bucket.logs resource
aws_s3_bucket.main resource
aws_s3_bucket.regional resource
aws_s3_bucket.regional_logs resource
aws_s3_bucket_lifecycle_configuration.logs resource
aws_s3_bucket_lifecycle_configuration.main resource
aws_s3_bucket_lifecycle_configuration.regional resource
aws_s3_bucket_lifecycle_configuration.regional_logs resource
aws_s3_bucket_logging.main resource
aws_s3_bucket_logging.regional resource
aws_s3_bucket_notification.main resource
aws_s3_bucket_notification.regional resource
aws_s3_bucket_policy.logs resource
aws_s3_bucket_policy.main resource
aws_s3_bucket_policy.regional resource
aws_s3_bucket_policy.regional_logs resource
aws_s3_bucket_public_access_block.logs resource
aws_s3_bucket_public_access_block.main resource
aws_s3_bucket_public_access_block.regional resource
aws_s3_bucket_public_access_block.regional_logs resource
aws_s3_bucket_server_side_encryption_configuration.logs resource
aws_s3_bucket_server_side_encryption_configuration.main resource
aws_s3_bucket_server_side_encryption_configuration.regional resource
aws_s3_bucket_server_side_encryption_configuration.regional_logs resource
aws_s3_bucket_versioning.logs resource
aws_s3_bucket_versioning.main resource
aws_s3_bucket_versioning.regional resource
aws_s3_bucket_versioning.regional_logs resource
aws_s3vectors_vector_bucket.main resource
aws_security_group.alb resource
aws_sqs_queue.vector_store resource
aws_sqs_queue.vector_store_dead_letter resource
aws_sqs_queue_redrive_allow_policy.vector_store_dead_letter resource
aws_vpc_security_group_egress_rule.alb_to_ecs resource
aws_vpc_security_group_ingress_rule.alb_http_ipv4 resource
aws_vpc_security_group_ingress_rule.alb_http_ipv6 resource
aws_vpc_security_group_ingress_rule.alb_https_ipv4 resource
aws_vpc_security_group_ingress_rule.alb_https_ipv6 resource
aws_vpc_security_group_ingress_rule.ecs_from_alb resource
aws_wafv2_web_acl.main resource
aws_wafv2_web_acl_association.main resource
aws_wafv2_web_acl_logging_configuration.main resource
random_id.main resource
random_password.api_key resource
random_password.realtime_client_secret_key resource
aws_caller_identity.current data source
aws_iam_policy_document.batch data source
aws_iam_policy_document.batch_assume_role data source
aws_iam_policy_document.log_kms_policy data source
aws_iam_policy_document.logs data source
aws_iam_policy_document.main_bucket_policy data source
aws_iam_policy_document.regional_bucket_policy data source
aws_iam_policy_document.regional_logs data source
aws_iam_policy_document.server data source
aws_iam_policy_document.server_services data source
aws_iam_policy_document.vectors_kms_policy data source
aws_partition.current data source
aws_region.current data source
aws_route53_zone.by_name data source
aws_s3_bucket.user_provided data source

Inputs

Name Description Type Default Required
ai_response_timeout Maximum time in seconds to wait for an AI model to complete a response. Applies to both streaming and non-streaming requests. The default of 600 seconds accommodates models with extended reasoning. Increase for long-running requests (e.g., large document analysis); decrease to fail fast on unexpectedly slow responses. Default to 600. number null no
alarms_enabled Enable CloudWatch alarms. This should be set to true if sns_topic_arn is provided. bool false no
alb_access_logging_enabled If true, enable ALB access logging to a dedicated S3 bucket. Security Hub: ELB.5 (Application Load Balancers should have logging enabled) — default true = pass; only relevant when var.alb_enabled is true. bool true no
alb_certificate_arn Existing ACM certificate ARN to attach to the HTTPS listener. When specified, takes precedence over certificate_create. If not specified and certificate_create is true, a certificate will be created automatically. string null no
alb_certificate_create If true, create an ACM certificate and validate it via DNS. Only used when certificate_arn is not specified. Requires route53_zone_id, domain_name, and route53_zone_private=false. bool true no
alb_domain_name Primary domain name for the application (e.g., api.example.com). Creates Route 53 A record and ACM certificate. If route53_zone_id is not specified, automatically looks up the most specific parent domain zone. string null no
alb_enabled If true, create an Application Load Balancer for the ECS service. Cannot be used with external subnets (subnet_ids). bool false no
alb_idle_timeout The time in seconds that the connection is allowed to be idle. Range: 1-4000 seconds. Default to 3600 (1 hour) to support slow LLM responses and long-running operations like AWS Transcribe. number 3600 no
alb_ingress_ipv4_cidrs List of IPv4 CIDR blocks allowed to access the ALB. Default to ['0.0.0.0/0'] for public access. list(string)
[
"0.0.0.0/0"
]
no
alb_ingress_ipv6_cidrs List of IPv6 CIDR blocks allowed to access the ALB. Default to ['::/0'] for public access. list(string)
[
"::/0"
]
no
alb_public If true, create a public (internet-facing) ALB with dedicated public subnets. If false, create a private (internal) ALB using app subnets. bool false no
alb_route53_zone_id Route 53 hosted zone ID for DNS records. If not specified, automatically infers the zone from the parent domain of domain_name (e.g., 'api.example.com' → 'example.com', 'api.sandbox.example.com' → 'sandbox.example.com'). string null no
alb_route53_zone_name Route 53 hosted zone name for DNS records (e.g., 'example.com'). Alternative to route53_zone_id - module will look up the zone ID automatically. If specified with domain_name, creates DNS records and ACM certificate. string null no
alb_route53_zone_private If true, the Route 53 zone is private. If false, it's public. Used when looking up the zone by name. bool false no
alb_ssl_policy SSL/TLS security policy for the ALB HTTPS listener. Defaults to the AWS-recommended post-quantum policy. See https://docs.aws.amazon.com/elasticloadbalancing/latest/application/describe-ssl-policies.html string "ELBSecurityPolicy-TLS13-1-2-Res-PQ-2025-09" no
alb_waf_block_anonymous_ips If true, block requests from anonymous IP addresses (VPNs, proxies, Tor exit nodes). bool false no
alb_waf_enabled If true, create a WAF WebACL and associate it with the ALB (requires alb_enabled=true). bool false no
alb_waf_logging_enabled If true, enable WAF logging to CloudWatch Logs. bool true no
alb_waf_rate_limit Maximum number of requests allowed from a single IP address in a 5-minute period. If null, rate limiting is disabled. number null no
anthropic_beta_allowlist Additional anthropic_beta flags to allow beyond the built-in defaults. Comma-separated string. Merged with the built-in set of Bedrock-supported flags. Only effective when anthropic_beta_filter is true. string null no
anthropic_beta_filter Enable filtering of unsupported anthropic_beta flags for Anthropic Claude models. When enabled, flags not in the allowlist are silently removed to prevent Bedrock ValidationException errors. Default to true. bool null no
anthropic_routes_prefix Anthropic API compatible routes prefix. Default to '/anthropic'. string null no
api_key API key for client authentication. When specified, all API requests must include this key. Mutually exclusive with api_key_create, api_key_ssm_parameter, and api_key_secretsmanager_secret. string null no
api_key_create If true, generate and return an API key using the 'api_key' output. When specified, all API requests must include this key. Mutually exclusive with api_key, api_key_ssm_parameter, and api_key_secretsmanager_secret. bool false no
api_key_secretsmanager_key Key name within the AWS Secrets Manager secret containing the API key. Only used when api_key_secretsmanager_secret is specified. string null no
api_key_secretsmanager_secret AWS Secrets Manager secret name containing the API key. Mutually exclusive with api_key_create, api_key, and api_key_ssm_parameter. When using this option, you must create an IAM policy granting secretsmanager:GetSecretValue permission and pass the policy ARN to var.ecs_task_role_policy_arns. string null no
api_key_ssm_parameter AWS Systems Manager Parameter Store parameter name containing the API key. Mutually exclusive with api_key_create, api_key, and api_key_secretsmanager_secret. When using this option, you must create an IAM policy granting ssm:GetParameter permission and pass the policy ARN to var.ecs_task_role_policy_arns. string null no
authentication_mode Which client authentication methods this deployment accepts: 'any' for every method that is configured, 'api_key' for the API key only, or 'cognito' for Amazon Cognito user pool tokens only. The value asserts the intended security posture: the server fails to start when the selected method is not configured, and when a method that would be ignored is configured anyway, so a credential is never accepted or silently refused by accident. Default to 'any'. string null no
autoscaling_alb_target_requests_per_target Target number of ALB requests per ECS task for auto-scaling. If null or ALB not enabled, request-based scaling is disabled. number null no
autoscaling_cpu_target_percent Target CPU utilization percentage for auto-scaling. If null, uses AWS default. number null no
autoscaling_max_capacity Maximum number of ECS tasks for auto-scaling. If null, uses AWS default. number null no
autoscaling_memory_target_percent Target memory utilization percentage for auto-scaling. If null, memory-based scaling is disabled. number null no
autoscaling_min_capacity Minimum number of ECS tasks. If not specified, defaults to the number of availability zones. number null no
autoscaling_scale_in_cooldown Time in seconds after a scale-in activity completes before another scale-in can start. If null, uses AWS default. number null no
autoscaling_scale_out_cooldown Time in seconds after a scale-out activity completes before another scale-out can start. If null, uses AWS default. number null no
autoscaling_schedule_start Schedule to start the service if stopped. Format: cron(fields) or at(yyyy-mm-ddThh:mm:ss) in UTC. string null no
autoscaling_schedule_stop Schedule to stop/pause the service (scale to 0). Format: cron(fields) or at(yyyy-mm-ddThh:mm:ss) in UTC. string null no
autoscaling_spot_on_demand_min_capacity Minimum number of on-demand tasks when autoscaling_spot_percent is enabled. If not specified, defaults to autoscaling_min_capacity. number null no
autoscaling_spot_percent Percent of capacity over the minimum capacity to run with Fargate Spot (~70% cost discount). Set to 100 to use only Spot instances. Set to 0 to disable Spot instances. number 0 no
availability_zones_count Maximum count of availability zones to provision with the dedicated VPC. Default to all available availability zones. number null no
aws_adaptive_retry Enable adaptive retry mode for all AWS service calls. When enabled, the client dynamically adjusts its retry behavior based on observed error rates, slowing down when a service appears congested. Default to false. bool null no
aws_bedrock_allow_application_inference_profile_arn If True, allow users to pass application inference profile ARNs directly as model IDs. Application inference profiles are custom routing configurations for specific use cases. When disabled, only standard model IDs and configured profiles are accepted. bool null no
aws_bedrock_allow_cross_region_inference_profile_arn If True, allow users to pass cross-region inference profile ARNs directly as model IDs. Cross-region inference profiles enable routing to multiple regions for better availability. When disabled, only standard model IDs and configured profiles are accepted. bool null no
aws_bedrock_allow_external_web_access_override If true, allow clients to override aws_bedrock_external_web_access per request with the web search tool's 'external_web_access' field. When false, a request that sets a different value is rejected. Default to false. bool null no
aws_bedrock_allow_guardrail_override Allow users to override the global guardrail configuration at request level using headers (X-Amzn-Bedrock-GuardrailIdentifier, X-Amzn-Bedrock-GuardrailVersion, X-Amzn-Bedrock-Trace). When disabled and a global guardrail is configured, request headers are ignored for security. Defaults to false for security. bool null no
aws_bedrock_allow_mantle_project_override If true, allow clients to override the configured Amazon Bedrock Mantle project per request via the 'OpenAI-Project' / 'anthropic-workspace' header. Default to false. bool null no
aws_bedrock_allow_prompt_arn If true, allow users to reference an Amazon Bedrock Prompt Management prompt ARN in the OpenAI Responses API 'prompt.id' parameter, for example 'arn:aws:bedrock:us-east-1:123456789012:prompt/ABCDE12345:1'. The prompt template is rendered by Amazon Bedrock and its variables are filled from 'prompt.variables'. Setting it to true also grants the task role bedrock:GetPrompt and bedrock:RenderPrompt on every prompt of the account. Default to false, which rejects any 'prompt' parameter with a 400 error. bool null no
aws_bedrock_allow_prompt_router_arn If True, allow users to pass prompt router ARNs directly as model IDs. Prompt routers enable dynamic model selection based on prompt characteristics. When disabled, only standard model IDs and configured profiles are accepted. bool null no
aws_bedrock_allow_service_tier_override Allow users to select the service tier at request level, through the 'service_tier' request parameter or the X-Amzn-Bedrock-Service-Tier header. When disabled, a request cannot change the tier configured for the model by default_model_service_tiers or by the model alias it names. A model with no configured tier still honors the request in either case. Defaults to true. bool null no
aws_bedrock_batch_role_arn ARN of an existing IAM service role Amazon Bedrock assumes to run batch inference jobs. Its trust policy must allow 'bedrock.amazonaws.com' to assume it, and it must be able to read and write every bucket the server may use, under aws_s3_batches_prefix; this module grants the task role 'iam:PassRole' on this ARN alone, for Amazon Bedrock only. When specified, takes precedence over aws_bedrock_batch_role_create. Default to none, meaning a role is created when aws_bedrock_batch_role_create is true, and the Batch API is disabled otherwise. string null no
aws_bedrock_batch_role_create If true, create the IAM service role Amazon Bedrock assumes to run batch inference jobs, allowed to read the submitted requests and write the results under aws_s3_batches_prefix in the module-managed buckets, and to invoke foundation models and inference profiles. Only used when aws_bedrock_batch_role_arn is not specified. When aws_bedrock_batch_role_arn is specified, this value is ignored. Default to false (Batch API disabled). bool false no
aws_bedrock_cross_region_inference If true, allow cross region inference to be used. Default to true. bool null no
aws_bedrock_cross_region_inference_global If True, allow 'global' cross region inference that can route requests to any region, worldwide. Default to true. bool null no
aws_bedrock_deprecated_model_fallback If true, requests that use a deprecated model ID are transparently retried with the recommended replacement model instead of returning a 404 error. Disable if you want deprecated model IDs to fail explicitly so clients are forced to migrate. Default to true. bool null no
aws_bedrock_deprecated_models Additional deprecated model ID mappings, merged with the built-in deprecation registry at startup. User-provided entries take precedence over built-in ones.

Keys are deprecated model IDs, values are the recommended replacement model IDs.

Example: { "my-old-model-v1" = "my-new-model-v2" }
map(string) null no
aws_bedrock_external_web_access If true, let the built-in web search tool reach the public web instead of answering from the Amazon Bedrock web index and cache. Requires the 'bedrock-websearch:ExternalWebAccess' IAM permission, granted by this module when enabled. Default to false. bool null no
aws_bedrock_guardrail_identifier Amazon Bedrock Guardrails ID. string null no
aws_bedrock_guardrail_trace Amazon Bedrock Guardrails trace setting: disabled, enabled, or enabled_full. string null no
aws_bedrock_guardrail_version Amazon Bedrock Guardrails version. string null no
aws_bedrock_knowledge_base_ids Allowlist of Amazon Bedrock knowledge bases served through the Vector Stores API. Each allowlisted knowledge base is addressed as the vector store vs_kb_<knowledgeBaseId> on every /v1/vector_stores endpoint and is listed alongside the stores the server owns: searching runs against it, attaching a file ingests a document, listing and reading files report its documents back, and deleting a file deletes the document.

Write each entry as <knowledgeBaseId>, or as <knowledgeBaseId>/<dataSourceId> when the knowledge base has more than one data source; with a single data source the server resolves it itself. For example ["ABCDE12345", "FGHIJ67890/KLMNO13579"]. Each knowledge base must live in the first aws_bedrock_regions region, which is the region this module grants access to it in.

The knowledge base stays yours: this module never creates or deletes one, and the task role is granted no action that would reshape it, only bedrock:Retrieve and the document actions of its data source, on the ARN of each listed knowledge base.

Default to an empty list, which grants no permission on any knowledge base and makes none of them addressable: a vs_kb_... identifier is then answered exactly as an unknown vector store is.
list(string) [] no
aws_bedrock_legacy If true, allow legacy Bedrock models to be used. Default to false. bool null no
aws_bedrock_mantle_enabled If true (application default), expose models served by the Amazon Bedrock Mantle endpoint (OpenAI GPT, xAI Grok, Google Gemma, and more) in addition to the classic Bedrock Converse models. Set to false to disable Mantle. When enabled but Mantle is unreachable or the region lacks the service, Mantle models are simply not listed. bool null no
aws_bedrock_mantle_preferred_models Model IDs (or ID prefixes) served by Amazon Bedrock Mantle even when also available on the classic bedrock-runtime endpoint. Default to none (bedrock-runtime preferred). list(string) null no
aws_bedrock_mantle_project Default Amazon Bedrock Mantle project (workspace) ID used to attribute Mantle inference requests for cost tracking and observability. A bare project ID such as 'proj_abc123' or 'default' (not an ARN). Default to none. string null no
aws_bedrock_mantle_regions List of AWS regions used for Amazon Bedrock Mantle, in failover priority order. Default to var.aws_bedrock_regions. list(string) null no
aws_bedrock_mantle_service_header If true, honor the 'x-stdapi-service: bedrock-mantle' request header to route a dual-homed model through Bedrock Mantle for that request. Cannot be combined with Bedrock Guardrails. Default to false. bool null no
aws_bedrock_marketplace_auto_subscribe If true, allow the server to automatically subscribe to new models in the AWS Marketplace. Default to true. bool null no
aws_bedrock_max_retries Maximum number of retries for Bedrock invocations. When region routing is enabled, retries cycle through all available regions. Default to 9. number null no
aws_bedrock_model_arn_mapping Map standard model IDs to custom inference profile or prompt router ARNs. This allows server administrators to override the default cross-region inference profiles with custom application inference profiles, cross-region inference profiles, or prompt routers.

Supported ARN types:
- Cross-region inference profile: arn:aws:bedrock:REGION:ACCOUNT:inference-profile/ID
- Application inference profile: arn:aws:bedrock:REGION:ACCOUNT:application-inference-profile/ID
- Prompt router: arn:aws:bedrock:REGION:ACCOUNT:default-prompt-router/ID

Example: {
"anthropic.claude-3-5-sonnet-20241022-v2:0" = "arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/my-custom-profile"
"anthropic.claude-haiku-4-5-20251001-v1:0" = "arn:aws:bedrock:us-east-1:123456789012:default-prompt-router/my-router"
}
map(string) null no
aws_bedrock_model_region_restrict Restrict a model to specific region(s) only. Can be used when a model provides important features only in certain regions.

Keys are Bedrock model IDs (or prefixes), values are ordered lists of allowed regions. When set, the model will only be available in the listed regions (intersected with the regions where it is actually available).

Example: { "amazon.nova-pro-v1:0" = ["us-east-1"] }

Use case: Nova grounding is only available in us-east-1, so restricting nova-pro to us-east-1 ensures grounding always works.
map(list(string)) null no
aws_bedrock_region_routing Automatic region routing strategy for Bedrock invocations. Distributes requests across configured regions to handle quota limits and regional unavailability. Strategies: 'disabled' (no routing), 'ordered' (try regions in configured order, default), 'lowest_latency' (prefer region with lowest measured latency), 'round_robin' (distribute evenly, incompatible with prompt caching). Requires at least 2 regions in aws_bedrock_regions. string null no
aws_bedrock_region_routing_max_quota_backoff_seconds Hard ceiling in seconds on the exponential quota backoff for a single region. Quota backoff doubles on each consecutive error; this value caps how high it can grow. Only effective when aws_bedrock_region_routing is not 'disabled'. Default to 3600 (1 hour). number null no
aws_bedrock_region_routing_quota_backoff_seconds Seconds to avoid a region after receiving a quota/throttling error. Only effective when aws_bedrock_region_routing is not 'disabled'. Default to 60. number null no
aws_bedrock_region_routing_quota_stale_factor Multiplier applied to the max quota backoff to compute the stale-error threshold. If the most recent quota error for a region is older than (max_quota_backoff * factor) seconds, the consecutive-error counter is reset. Only effective when aws_bedrock_region_routing is not 'disabled'. Default to 2. number null no
aws_bedrock_region_routing_unavailable_backoff_seconds Seconds to avoid a region after receiving an unavailability error. Only effective when aws_bedrock_region_routing is not 'disabled'. Default to 30. number null no
aws_bedrock_regions List of AWS regions where Bedrock AI models are available. Default to the current region. list(string) null no
aws_bedrock_session_encryption_key_arn KMS key ARN encrypting the AWS Bedrock sessions that back stored responses and chat completions (store=true). Default to the AWS-managed key. string null no
aws_bedrock_user_role_arn ARN of an IAM role the server assumes once per end user, so AWS reports Amazon Bedrock model usage per end user in Cost Explorer and the Cost and Usage Report. The role's trust policy must allow this module's task role to call both 'sts:AssumeRole' and 'sts:TagSession' on it; this module grants the task role those two actions on this ARN. Default to none (all usage reported under the task role). string null no
aws_bedrock_user_role_require_identity If true, reject a model request that identifies no end user instead of running it under the server's own identity. Requires aws_bedrock_user_role_arn. Default to false. bool null no
aws_bedrock_user_role_session_duration Lifetime in seconds of a per-end-user role session obtained with aws_bedrock_user_role_arn, from 900 to 3600. The ceiling is imposed by AWS: a role session obtained from another role session cannot last longer than one hour. Default to 3600. number null no
aws_bedrock_user_role_tag_key Session tag key carrying the end user identity on per-end-user role sessions. Activate it as a cost allocation tag of type 'IAM principal' to group Bedrock costs per end user, and test it in IAM policies as 'aws:PrincipalTag/'. Default to 'user'. string null no
aws_cognito_accept_id_token If true, accept Amazon Cognito identity tokens in addition to access tokens. Identity tokens describe the signed-in user rather than granting API access, and carry no scopes; enable only for clients that cannot obtain an access token. Default to false. bool null no
aws_cognito_client_ids Amazon Cognito user pool application client IDs whose tokens are accepted, as a comma-separated list. A token issued to any other application is rejected. Required when aws_cognito_user_pool_id is specified. string null no
aws_cognito_issuer_type Issuer configuration of the Amazon Cognito user pool, which decides the issuer URL its tokens carry: 'original' for 'https://cognito-idp..amazonaws.com/', or 'updated' for 'https://issuer-cognito-idp..amazonaws.com/', available on the Essentials and Plus pool tiers. Tokens whose issuer does not match are rejected, so this must match the pool's own setting. Default to 'original'. string null no
aws_cognito_required_scopes OAuth 2.0 scopes a token must all carry to be accepted, as a comma-separated list. Custom scopes exist only on tokens obtained from the user pool's OAuth 2.0 token endpoint, which requires a resource server and a pool domain; tokens obtained by signing in with a username and password carry only 'aws.cognito.signin.user.admin', so requiring a custom scope rejects them. Default to none (any scope set is accepted). string null no
aws_cognito_user_pool_id Identifier of the Amazon Cognito user pool whose tokens authenticate clients, for example 'eu-west-3_a1b2c3d4e'. Clients send a pool access token in the 'Authorization: Bearer ' header; its signature, issuer, expiry, application and scopes are validated on every request. The identifier is prefixed by the pool's AWS Region, which is where the signing keys are read from. Requires aws_cognito_client_ids. Default to none (user pool authentication disabled). string null no
aws_comprehend_region AWS region for Comprehend language detection service. Default to every var.aws_bedrock_regions region as a failover candidate, or the current region. string null no
aws_connect_timeout Timeout in seconds for establishing a connection to an AWS service endpoint. Keeping this value short allows fast failover to another region when a connection cannot be established. Default to 5. number null no
aws_failover_max_retries Maximum SDK retry attempts per candidate region for the multi-region failover services (Polly, Transcribe, Translate, Comprehend). Only applied when the service has several candidate regions (no dedicated region setting configured). Default to 2. number null no
aws_max_pool_connections Maximum number of concurrent HTTP connections per AWS service client. Each AWS service client (per region) maintains its own connection pool up to this limit. Increase if you observe connection pool exhaustion under high concurrency. Default to 50. number null no
aws_polly_region AWS region for Polly text-to-speech service. Default to every var.aws_bedrock_regions region as a failover candidate, or the current region. string null no
aws_s3_accelerate Enable S3 Transfer Acceleration for presigned URLs. Default to false. bool null no
aws_s3_accepted_buckets S3 buckets that the application has read access to, mapped to their region. These buckets can be used as input S3 data sources, and S3 HTTP URLs (including presigned URLs) for these buckets will be automatically converted to S3 URIs for direct access.

Keys are bucket names, values are AWS region identifiers.

Example: { "my-data-bucket" = "us-east-1", "my-eu-bucket" = "eu-west-1" }

If not specified, only the application's own S3 buckets (aws_s3_bucket and aws_s3_regional_buckets) are recognized for S3 URI conversion.
map(string) null no
aws_s3_accepted_buckets_kms_key_arn List of KMS key ARNs used to encrypt the accepted S3 buckets (var.aws_s3_accepted_buckets). Required to grant the server permissions to decrypt objects from KMS-encrypted accepted buckets. list(string) null no
aws_s3_batches_prefix S3 prefix (folder path) for the Batch API's own data — the submitted requests, the results and the batch records themselves. Each batch stores its data under a folder of its own below this prefix, in the bucket that served it, and the batch service role is granted access to this prefix alone. Must not be the bucket root. Default to 'batches/'. string null no
aws_s3_bucket Existing S3 bucket name for storing generated files and application data. When specified, takes precedence over aws_s3_bucket_create. If not specified and aws_s3_bucket_create is true, a bucket will be created automatically. string null no
aws_s3_bucket_create If true, create an S3 bucket for the application. Only used when aws_s3_bucket is not specified. When aws_s3_bucket is specified, this value is ignored. bool true no
aws_s3_buckets_kms_keys_arns List of KMS key ARNs used to encrypt user-provided regional S3 buckets specified in aws_s3_regional_buckets.
Required to grant the server permissions to access encrypted regional buckets.
When using aws_s3_regional_buckets_create = true (default), KMS keys are created automatically and do not need to be specified here.
list(string) [] no
aws_s3_files_prefix S3 prefix (folder path) for Files API objects. Default to 'files/'. string null no
aws_s3_regional_buckets By default (aws_s3_regional_buckets_create = true), buckets are created automatically for every region in aws_bedrock_regions not listed here. Use this variable only to point to existing buckets you manage yourself.

Keys are AWS region identifiers, values are bucket names.

Example: { "us-east-1" = "my-bucket-us-east-1", "us-west-2" = "my-bucket-us-west-2" }

Required for Bedrock operations with multimodal input or document processing.
map(string) null no
aws_s3_regional_buckets_create If true (default), create regional S3 buckets and per-region KMS keys for every region in aws_bedrock_regions
not already present as a key of aws_s3_regional_buckets and not equal to the provider's primary region.

Set to false to disable automatic creation (for example, if you manage these buckets out-of-band).
bool true no
aws_s3_tmp_prefix S3 prefix (folder path) for temporary files used during job processing. Default to 'tmp/'. string null no
aws_s3_vector_stores_prefix S3 prefix (folder path) in the general purpose bucket for the Vector Stores API's own records — the stores, their attached files and their file batches. Default to 'vector_stores/'. string null no
aws_s3_vectors_bucket Existing Amazon S3 vector bucket name backing the Vector Stores API. A vector bucket is a distinct resource type from a general purpose bucket. When specified, takes precedence over aws_s3_vectors_bucket_create. Default to none, meaning a bucket is created when aws_s3_vectors_bucket_create is true, and the Vector Stores API is disabled otherwise. string null no
aws_s3_vectors_bucket_create If true, create an S3 vector bucket backing the Vector Stores API. Only used when aws_s3_vectors_bucket is not specified. When aws_s3_vectors_bucket is specified, this value is ignored. Default to false (Vector Stores API disabled). bool false no
aws_s3_vectors_kms_key_arn KMS key ARN encrypting the vector bucket specified in aws_s3_vectors_bucket. Required to grant the server permission to use an SSE-KMS encrypted vector bucket. When using aws_s3_vectors_bucket_create = true, a key is created automatically and does not need to be specified here. string null no
aws_s3_vectors_region AWS region holding the vector bucket. A vector bucket is a regional resource and its indexes are only reachable in that region, so this setting has no failover. Default to the region this module is deployed in.

Amazon S3 Vectors is not available in every region: see AWS Regions, endpoints, and quotas for S3 Vectors.
string null no
aws_s3_videos_expires_after Retention period in seconds for generated videos. When set, Video.expires_at is reported, expired downloads return 404, and a matching S3 Lifecycle expiration rule is created on the module-managed buckets. Default to no expiry. number null no
aws_s3_videos_prefix S3 prefix (folder path) for videos generated through the Videos API. Default to 'videos/'. string null no
aws_sqs_vector_store_queue_create If true, create the Amazon SQS queue, and its dead-letter queue, that make vector store indexing durable: a file attached to a store keeps being indexed by another task when the task that accepted it stops, instead of being reported as failed. Only used when the Vector Stores API is enabled and aws_sqs_vector_store_queue_url is not specified. When aws_sqs_vector_store_queue_url is specified, this value is ignored. Default to true. bool true no
aws_sqs_vector_store_queue_kms_key_arn KMS key ARN encrypting the queue specified in aws_sqs_vector_store_queue_url. Required to grant the server permission to use an SSE-KMS encrypted queue; leave unset for a queue encrypted with the Amazon SQS managed key. When using aws_sqs_vector_store_queue_create = true, the deployment key is used automatically and does not need to be specified here. string null no
aws_sqs_vector_store_queue_url URL of an existing Amazon SQS queue carrying the vector store indexing jobs. Must be a standard queue, never FIFO, and must have a dead-letter queue: a file the server cannot index is settled as failed once its deliveries run out, and its message is kept in the dead-letter queue. The queue is reached in the single region its URL names, and only ever carries identifiers, never file content. Requires the Vector Stores API to be enabled: the server refuses to start with a queue and nothing to index. When specified, takes precedence over aws_sqs_vector_store_queue_create. Default to none, meaning a queue is created when aws_sqs_vector_store_queue_create is true and the Vector Stores API is enabled, and indexing runs in the task that accepted the request otherwise. string null no
aws_transcribe_output_encryption_key_arn KMS key ARN encrypting the transcription job output written to aws_transcribe_s3_bucket. The key must be usable from every region a transcription job can be served from; this module grants the task role kms:GenerateDataKey and kms:Decrypt on it, and the key policy must allow the same actions. Default to the bucket's own default encryption. string null no
aws_transcribe_region AWS region for Transcribe speech-to-text service. Default to every var.aws_bedrock_regions region as a failover candidate, or the current region. string null no
aws_transcribe_s3_bucket AWS S3 bucket name for temporary file storage during transcription. Defaults to aws_s3_bucket if not specified. string null no
aws_transcribe_stream_languages Languages a streamed transcription (stream=true) picks between when the request names none, as two or more language codes, for example ['en-US', 'es-US', 'fr-FR']. A streamed transcription starts before the recording has been fully read, which requires knowing which languages to expect. Default to none, meaning a request naming no language is transcribed once the whole recording has been read, and its language detected. list(string) null no
aws_translate_region AWS region for Translate text translation service. Default to every var.aws_bedrock_regions region as a failover candidate, or the current region. string null no
cloudwatch_logs_retention_in_days Cloudwatch logs retention in days. Applies to every log group this module and its child modules create, including the Container Insights performance log group. Security Hub: CloudWatch.16 (CloudWatch log groups should be retained for a specified time period) requires at least 365 days by default — default 365 = pass; lowering it fails this control. number 365 no
cloudwatch_metrics If True, emit per-request AWS-billed usage as CloudWatch Embedded Metric Format (EMF) log lines. Default to false. bool null no
cloudwatch_metrics_namespace CloudWatch namespace for the emitted usage metrics. Default to 'stdapi'. string null no
cohere_routes_prefix Cohere API compatible routes prefix. Default to '/cohere'. string null no
compliance_vpc_endpoints_enabled If true, add the interface VPC endpoints for ECR API, ECR Docker Registry, Systems Manager, SSM Incident Manager Contacts and SSM Incident Manager. Enable only if you have high compliance requirements — each interface endpoint adds cost. Security Hub: EC2.55/EC2.56/EC2.57/EC2.58/EC2.60 — default false = fail; set to true to pass. bool false no
container_insight Container insight configuration. Valid values: 'enhanced', 'enabled', 'disabled'. Default to 'enabled'. Security Hub: ECS.12 (ECS clusters should use Container Insights) — default 'enabled' = pass; setting 'disabled' fails this control. string "enabled" no
cors_allow_origins List of origins allowed to make cross-origin requests (CORS). Use ['*'] to allow all origins. Default to no CORS headers. list(string) null no
cost_price_overrides Unit price overrides for models not covered by the AWS Price List API, as a map of model IDs to dimension-name/price maps. map(map(number)) null no
cost_tracking Enable per-request cost estimation from AWS Price List values (adds the pricing:GetProducts permission). Reported costs are an estimate from published prices, not your actual AWS bill; use cost_price_overrides for models the Price List API does not cover. Default to false. bool null no
cpu ECS task CPU count. Valid values: 0.25, 0.5, 1, 2, 4, 8 & 16. Default of 0.25 vCPU is suitable for common use cases (text generation, embeddings). Increase for intensive workloads (multimodal requests, large LLM models). number 0.25 no
cpu_architecture CPU architecture. Valid values: 'X86_64' or 'ARM64'. string "ARM64" no
default_model_params Default inference parameters applied to specific models automatically. JSON string format. string null no
default_model_service_tiers Default service tier applied to specific models automatically when no explicit tier is provided (default, flex, priority, reserved). JSON string format, e.g. {"amazon.nova-pro-v1:0": "flex"}. string null no
default_tts_language Default text-to-speech language to use if not specified in the request. Default to language autodetection. string null no
default_tts_model Default text-to-speech model to use if not specified in the request. Default to 'amazon.polly-standard'. string null no
deletion_protection If true, enable deletion protection on eligible resources. bool false no
dns_firewall_action Action taken by DNS Firewall when a query matches a domain from var.dns_firewall_managed_domain_list_ids, and (if var.dns_firewall_advanced_enabled) a DNS Firewall Advanced threat detection. Valid values: 'ALLOW', 'BLOCK', 'ALERT'. 'ALLOW' isn't valid for DNS Firewall Advanced rules, so it's treated as 'BLOCK' for those only. Ignored if var.dns_firewall_enabled is false. string "BLOCK" no
dns_firewall_advanced_confidence_threshold Confidence threshold for DNS Firewall Advanced rules. Valid values: 'LOW', 'MEDIUM', 'HIGH'. Lower thresholds catch more threats at the cost of more false positives. Ignored if var.dns_firewall_advanced_enabled is false. string "HIGH" no
dns_firewall_advanced_enabled If true, add Route 53 Resolver DNS Firewall Advanced rules (additional cost) blocking DNS queries identified as domain generation algorithm (DGA) or DNS tunneling activity, on top of any managed-domain-list rules. Ignored if var.dns_firewall_enabled is false. bool false no
dns_firewall_enabled If true, create a Route 53 Resolver DNS Firewall rule group and associate it with the dedicated VPC, blocking/alerting on DNS queries per var.dns_firewall_managed_domain_list_ids and var.dns_firewall_advanced_enabled. Helps mitigate malicious-URL injection via user-supplied URL/file references (images, documents, audio) by blocking outbound DNS resolution to known-malicious domains, in addition to the application's own SSRF protection. Only supported for the dedicated VPC this module creates; cannot be enabled when using external subnets (var.subnet_ids). Not mapped to a Security Hub control; default false = feature not created. bool false no
dns_firewall_managed_domain_list_ids Map of AWS Managed Domain List name to ID (e.g. { "AWSManagedDomainsAggregateThreatList" = "rslvr-fdl-..." }) to block/alert on via var.dns_firewall_action. Defaults (null) to the Aggregate Threat List ID built into the underlying VPC module for the current region, covering commercial regions enabled by default — no AWS CLI call or extra permissions required. For a region not covered by that default, look up the ID with 'aws route53resolver list-firewall-domain-lists' and pass it explicitly. Ignored if var.dns_firewall_enabled is false. Set to {} to skip managed-list rules while still using var.dns_firewall_advanced_enabled. map(string) null no
dns_firewall_priority Processing priority for the DNS Firewall rule group association within the VPC (lower is processed first). Must be unique among all rule group associations on the same VPC, including ones created outside this module. Ignored if var.dns_firewall_enabled is false. number 101 no
drop_unsupported_system_prompt If true, system prompts are silently dropped when models don't support them. If false, an error is returned when a system prompt is passed to a model that doesn't support system prompts (e.g., mistral.mistral-7b models). Default: true for backward compatibility. bool null no
ecs_task_role_policy_arns List of IAM policy ARNs to attach to the ECS task role. Use this to grant additional permissions to the ECS task, such as access to SSM parameters or Secrets Manager secrets specified in api_key_ssm_parameter or api_key_secretsmanager_secret. list(string) [] no
enable_docs Enable interactive API documentation UI at /docs. Default to false. bool null no
enable_gzip Enable GZip compression middleware for HTTP responses. Disabled by default. bool null no
enable_mcp_sse Enable the MCP (Model Context Protocol) server using Server-Sent Events (SSE) transport. When enabled, exposes MCP endpoints at /sse. Maintained for backwards compatibility with older MCP clients; prefer enable_mcp_streamable_http for new deployments. Default to false. bool null no
enable_mcp_streamable_http Enable the MCP (Model Context Protocol) server using Streamable HTTP transport. When enabled, exposes an MCP-compatible endpoint at /mcp. This is the recommended MCP transport. Default to false. bool null no
enable_openapi_json Enable OpenAPI JSON schema endpoint at /openapi.json. Default to false. bool null no
enable_proxy_headers Enable ProxyHeadersMiddleware to trust X-Forwarded-* headers from reverse proxies. Automatically enabled when var.alb_enabled is true and var.log_client_ip is true. bool null no
enable_redoc Enable ReDoc API documentation UI at /redoc. Default to false. bool null no
extra_model_params_denylist Additional parameter names to strip from the 'extra model parameters' passthrough, as a comma-separated list. Merged with the built-in default denylist of client-control parameters (such as 'drop_params', 'api_key' or 'custom_llm_provider') that some OpenAI-SDK-based clients leak into extra_body and that are never legitimate Bedrock model parameters. Only effective when extra_model_params_drop_all is false. Default to the built-in denylist alone. Example: 'x_internal_debug_flag,x_proxy_trace_id' string null no
extra_model_params_drop_all If true, disable the 'extra model parameters' passthrough entirely: no undeclared request field is ever forwarded to Amazon Bedrock as a provider-specific inference parameter, on any route that supports it. Overrides extra_model_params_denylist, which no longer matters once nothing is forwarded. Default to false, which keeps the passthrough, filtered by the built-in default denylist and extra_model_params_denylist. bool null no
guardduty_vpc_endpoint_enabled If true, add the interface VPC endpoint required by GuardDuty Runtime Monitoring. Only relevant if you use GuardDuty Runtime Monitoring on resources in this VPC — leave false otherwise. Recommended whenever Runtime Monitoring is enabled, even with GuardDuty's automated agent configuration, since managing it here ensures correct subnet placement. Not mapped to a Security Hub control; default false = endpoint not created. bool false no
image_generation_model Default model ID for image generation (e.g. 'amazon.nova-canvas-v1:0'). Required unless the client or the LLM specifies a model per call. string null no
kms_key_id If specified, directly use this KMS key instead of creating a dedicated one for the application. string null no
log_client_ip If True, log the client IP address for each request and add it to OpenTelemetry spans. Default to false. bool null no
log_level Minimum logging level to output: info, warning, error, critical, or disabled. Default to info. string null no
log_request_params If True, add requests and responses parameters to logs. Should not be enabled in production. Default to false. bool null no
max_concurrent_input_downloads Maximum number of input files fetched or resolved concurrently within a single request, bounding outbound downloads against socket/memory exhaustion and SSRF amplification. Default to 8. number null no
max_input_file_size Maximum size in bytes of an inline input file loaded into memory (base64, data URI, or a downloaded HTTP(S)/S3 source). Requests exceeding it are rejected with HTTP 413 before the content is fully decoded. Default to 0 (no limit). number null no
mcp_exclude_tools Comma-separated list of MCP tool names to hide from MCP clients. All other tools remain exposed. When mcp_include_tools is also specified, these values are removed from it. Example: 'openai_files_delete,anthropic_files_delete' string null no
mcp_include_tools Comma-separated list of MCP tool names to expose exclusively. Only the listed tools will be available to MCP clients; all others are hidden. When both mcp_include_tools and mcp_exclude_tools are specified, mcp_exclude_tools values are removed from mcp_include_tools. Example: 'openai_chat_completion,openai_embedding,openai_model_list' string null no
mcp_stateless_http Serve the MCP Streamable HTTP transport in stateless mode. Each request is then handled by a fresh transport that keeps no session state, so any client may call /mcp without initializing a session first and any task may serve any request. Required by hosts that provide their own session isolation and inject an 'Mcp-Session-Id' header the server never issued. Requires enable_mcp_streamable_http. Default to false. bool null no
memory ECS task memory (MiB). Valid values depends on the var.container_cpu value (x1024), see the ECS documentation for more information. Default of 512 MiB is suitable for common use cases (text generation, embeddings). Increase for intensive workloads (multimodal requests, large LLM models). number 512 no
model_aliases Map of model aliases to actual model IDs.
Allows users to reference models using custom alias names.
This is merged with default system aliases at startup.
User-provided aliases take precedence over system defaults.

An alias maps either to a model ID, or to an object carrying that model plus
the configuration to apply to requests naming the alias: "service_tier",
"guardrail_id" with "guardrail_version" (and optionally "guardrail_trace"),
"metadata" and "extra_params". Those values override the equivalent
server-wide configuration, and a value sent with the request still wins
unless its override variable (aws_bedrock_allow_guardrail_override,
aws_bedrock_allow_service_tier_override) is disabled.

Example: {
"my-tts": "amazon.polly-neural",
"my-stt": "amazon.transcribe",
"my-chat": {
"model": "amazon.nova-lite-v1:0",
"service_tier": "flex",
"metadata": { "team": "research" },
"extra_params": { "temperature": 0.2 }
}
}
any null no
model_cache_seconds Cache lifetime in seconds for the Bedrock models list. number null no
name_prefix Prefix to add to all created resources names. string "stdapiai" no
nat_gateways_allowed If true, NAT gateways are used to give internet access to the application. If Disabled and internet access is required, application subnets will be public. Disable only if cost is privileged over security. bool true no
oauth_authorization_servers Issuer URLs of the OAuth 2.0 authorization servers that issue tokens for the API, as a comma-separated list, published in the protected resource metadata. Leave it unset when aws_cognito_user_pool_id is specified: the pool's own issuer is published, resolved for the partition the pool lives in. Setting it explicitly is for a deployment that accepts tokens from another authorization server, and the list must still name the configured pool's issuer. Required only when no user pool is configured and oauth_resource_identifier is. string null no
oauth_resource_identifier Public URL clients use to reach the API, for example 'https://api.example.com', which is normally 'https://' followed by alb_domain_name. Setting it publishes an OAuth 2.0 protected resource metadata document at '/.well-known/oauth-protected-resource' and puts that address in the challenge every 401 response carries, so an AI agent can discover where to obtain a token. Must be the exact origin clients dial: scheme and host, no path, no trailing slash. Requires either aws_cognito_user_pool_id, whose issuer is then published, or an explicit oauth_authorization_servers. If not specified, nothing is published. string null no
oauth_scopes_supported OAuth 2.0 scopes a token needs to call the API, as a comma-separated list, advertised in the protected resource metadata and in the 401 challenge. Requires oauth_resource_identifier. If not specified, aws_cognito_required_scopes is advertised, so the scopes a token needs are declared in one place. string null no
openai_routes_prefix OpenAI API compatible routes prefix. string null no
otel_enabled Enable OpenTelemetry distributed tracing. Default to false. bool null no
otel_exporter_endpoint OpenTelemetry traces export endpoint URL. string null no
otel_sample_rate OpenTelemetry trace sampling rate (0.0 to 1.0). number null no
otel_service_name Service name identifier for OpenTelemetry traces. Default to 'stdapi.ai'. string null no
proxy_trusted_hosts Trusted proxy hosts/IPs (CIDRs) whose X-Forwarded-* headers are honored when proxy headers are enabled. Restrict to your reverse proxy's IP range so direct clients cannot forge their source IP. Write entries in their natural address family: on an IPv6-enabled VPC the server binds a dual-stack socket and sees IPv4 peers in IPv4-mapped form, and the module adds the matching '::ffff:' range for every IPv4 entry automatically. When null and proxy headers are auto-enabled (var.alb_enabled and var.log_client_ip both true), defaults to the ALB subnet CIDRs so only the ALB is trusted; otherwise the server default ('*') applies. list(string) null no
realtime_allow_session_override Allow a client connecting to the Realtime API with an ephemeral client secret to override the session configuration that secret carries. When disabled, the model, the instructions and the output token cap minted into the secret are final: a 'model' query parameter naming another model is refused, and a session.update changing one of them answers an error. Default to true, which is the upstream behavior; disable it in a multi-tenant deployment where the secret is the only thing constraining an untrusted client. bool null no
realtime_client_secret_key Secret the ephemeral client secrets of the Realtime API are signed with. Any value works as long as every task of the deployment shares it: a secret minted by one task is verified by whichever one the client's WebSocket reaches. Passed to the container as an ECS secret stored in AWS Systems Manager Parameter Store, never as a plain environment variable.

When not specified, the server derives the key from the configured API key. When no API key is configured either (api_key, api_key_create, api_key_ssm_parameter and api_key_secretsmanager_secret all unset), the module generates a key and stores it the same way, because the server would otherwise fall back to a per-process random value, under which a client secret minted by one task is rejected by every other task and by any task replacing it after a deployment.
string null no
security_group_id If specified and 'subnet_ids' is specified, use this security group instead of creating a new one giving access to internet and AWS services. string null no
service_discovery_dns_name DNS name for service discovery. By default, uses the service name. Only if service_discovery_dns_namespace_id is specified. string null no
service_discovery_dns_namespace_id If specified, enable Service discovery on the ECS service and attach it to this Cloud Map namespace. string null no
shutdown_drain_timeout Maximum time in seconds the server waits, once asked to stop, for background work that requests started and did not wait for: temporary file cleanups, vector store file indexing, and the release of live audio sessions. Work still running when the wait ends is cancelled and counted as a warning in the server's stop log event. This wait is best effort, not a delivery guarantee: a container runtime sends SIGKILL a fixed delay after the stop signal. This module raises the task's own stop timeout to match, so the wait is not cut short here; a deployment that does not use this module must raise it itself, because the default on Amazon ECS is 30 seconds. Values above 110 are capped, since Fargate accepts at most 120. Set to 0 to stop as fast as possible, cancelling background work immediately. Default to 10. number null no
sns_topic_arn SNS topic ARN for CloudWatch alarms. If specified, CloudWatch alarms will be created for high memory usage and unhealthy containers. string null no
ssrf_protection_block_private_networks Enable SSRF protection by blocking requests to private/local networks. When enabled, the server will reject requests to RFC 1918 private addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), loopback, link-local, reserved, and multicast addresses. Default to true. bool null no
strict_input_validation If True, raise error on extra fields in input request. Default to false. bool null no
subnet_ids If specified, directly use theses subnets instead of creating a dedicated VPC. list(string) [] no
timezone Timezone for request date & time (IANA timezone identifier). Default to UTC. string null no
tokens_estimation Deprecated and ignored since stdapi.ai v1.14.0: token estimation has been removed; only real AWS-billed usage is reported. bool null no
tokens_estimation_default_encoding Deprecated and ignored since stdapi.ai v1.14.0: token estimation has been removed. string null no
trusted_hosts List of trusted host header values for Host header validation. Supports wildcard subdomains. Disabled by default. list(string) null no
vector_store_chunk_overlap_tokens Default number of tokens shared between consecutive chunks, for files indexed into a vector store without an explicit chunking_strategy. Must not exceed half of vector_store_chunk_size_tokens, which the server checks on startup. Default to 400. number null no
vector_store_chunk_size_tokens Default chunk size, in tokens, for files indexed into a vector store without an explicit chunking_strategy; a request's own chunking_strategy always wins. Tokens are approximated from the text length, and a chunk is additionally capped by what the embedding model accepts in one input. Default to 800. number null no
vector_store_embedding_model Model used to embed the files indexed into a vector store, and the queries searched against them. The model is frozen on each store when it is created, so changing it only affects stores created afterwards; existing stores keep answering with the model they were created with. Default to 'amazon.titan-embed-text-v2:0'. string null no
version_to_deploy Container image version tag from AWS Marketplace. Leave unset to automatically use the latest stable version. Only override for testing or rollback purposes. A '-arm64' or '-amd64' suffix is appended automatically based on var.cpu_architecture, so the value must not include an architecture suffix. string "1.16.1" no
vpc_cidr CIDR block for the dedicated VPC. string "10.0.0.0/16" no
vpc_endpoints_allowed If true, VPC endpoints interfaces are privileged to give AWS services access to the application if no internet access is required. VPC endpoint Gateway are always provisioned. Disable only if cost is privileged over security. bool true no
vpc_flow_log_enabled If true, enable VPC flow log. Disable only if cost is privileged over security. bool true no

Outputs

Name Description
alb_arn ARN of the Application Load Balancer (only if ALB is enabled).
alb_dns_name DNS name of the Application Load Balancer (only if ALB is enabled).
alb_security_group_id Security group ID of the Application Load Balancer (only if ALB is enabled).
alb_waf_web_acl_arn ARN of the WAF WebACL (only if WAF is enabled).
alb_waf_web_acl_id ID of the WAF WebACL (only if WAF is enabled).
alb_zone_id Zone ID of the Application Load Balancer (only if ALB is enabled).
api_key Returns API key value from var.api_key or var.api_key_create. API key values from var.api_key_ssm_parameter or var.api_key_secretsmanager_secret are not returned.
application_url Application URL (uses domain name if configured, otherwise ALB DNS name).
aws_s3_tmp_prefix S3 prefix (folder path) for temporary files used during job processing. To pass to compagnon module.
bedrock_batch_role_arn ARN of the IAM service role Amazon Bedrock assumes to run batch inference jobs, or null when the Batch API is disabled.
bucket_arn Configuration S3 bucket ARN.
bucket_id Configuration S3 bucket ID.
cloudwatch_log_groups_names CloudWatch log group names for each container in the server.
cluster_name ECS cluster name.
deletion_protection If true, enable deletion protection on eligible resources. To pass to compagnon module.
kms_key_arn KMS key ARN.
kms_key_id KMS key ID.
kms_policy_documents_json KMS policy documents to add to the policy of the key specified via var.kms_key_id.
name_prefix Name prefix for resources. To pass to compagnon module.
port Container port exposed by the application.
regional_buckets Map of region → bucket name (user-provided + auto-created).
security_group_id Security group ID for the ECS server service.
service_discovery_service_name Service discovery service name for the server (only if service discovery is enabled).
service_name ECS service name.
subnet_ids Subnets IDs where the ECS service is deployed.
vector_store_queue_arn ARN of the Amazon SQS queue carrying the vector store indexing jobs, or null when durable indexing is disabled.
vector_store_queue_url URL of the Amazon SQS queue carrying the vector store indexing jobs, or null when durable indexing is disabled.
vectors_bucket_name S3 vector bucket name backing the Vector Stores API, or null when it is disabled.
vectors_region Region holding the S3 vector bucket, or null when the Vector Stores API is disabled.

About

Terraform module to deploy stdapi.ai on AWS ECS Fargate — a self-hosted OpenAI, Anthropic and Cohere compatible AI gateway for Amazon Bedrock.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages