Adds a terraform/ directory with an opinionated module that deploys shared-memory to ECS Fargate behind an ALB. The module assumes the operator already provides the VPC, RDS Postgres, ACM cert, ECR images, and OIDC clients, and creates everything else: ECS cluster + services, ALB, Service Connect namespace for app-embedder discovery, EFS-backed model cache for the embedder, Secrets Manager entries, IAM roles, CloudWatch log groups, and a one-shot migrator task definition. Includes examples/basic/ with a worked invocation and a README covering prerequisites, quick start, the post-apply migrator run, image updates, DNS setup, and a security note. Main README gains a short Mode C pointer to the terraform/ guide. Validated with `terraform fmt -check -recursive` and `terraform validate` against AWS provider 5.x. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
198 lines
5.5 KiB
Terraform
198 lines
5.5 KiB
Terraform
# -----------------------------------------------------------------------------
|
|
# Inputs. Required vars have no default; everything else has a sensible one.
|
|
#
|
|
# Secrets (database_url, *_secret) are marked sensitive so they don't surface
|
|
# in `terraform plan` / `apply` output. They still flow through state, so
|
|
# protect the state backend accordingly (see README "Security note").
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# -------- Identity / wiring --------
|
|
|
|
variable "name_prefix" {
|
|
description = "Prefix applied to every named resource (e.g. shared-memory-prod). Keep under 24 chars so generated names stay within AWS limits."
|
|
type = string
|
|
}
|
|
|
|
variable "vpc_id" {
|
|
description = "ID of the VPC where the ALB, ECS tasks, EFS, and security groups are created."
|
|
type = string
|
|
}
|
|
|
|
variable "public_subnet_ids" {
|
|
description = "Public subnets (at least 2 AZs) that host the ALB."
|
|
type = list(string)
|
|
|
|
validation {
|
|
condition = length(var.public_subnet_ids) >= 2
|
|
error_message = "Provide at least two public subnets for ALB HA."
|
|
}
|
|
}
|
|
|
|
variable "private_subnet_ids" {
|
|
description = "Private subnets (at least 2 AZs) where ECS tasks and EFS mount targets live."
|
|
type = list(string)
|
|
|
|
validation {
|
|
condition = length(var.private_subnet_ids) >= 2
|
|
error_message = "Provide at least two private subnets for task HA."
|
|
}
|
|
}
|
|
|
|
# -------- TLS / DNS --------
|
|
|
|
variable "acm_certificate_arn" {
|
|
description = "ACM certificate ARN attached to the ALB's HTTPS listener. Must be in the same region as the ALB."
|
|
type = string
|
|
}
|
|
|
|
variable "domain_name" {
|
|
description = "Public hostname (e.g. memory.example.com). Used to build PUBLIC_URL/AUTH_URL passed to the app."
|
|
type = string
|
|
}
|
|
|
|
# -------- Container images --------
|
|
|
|
variable "app_image" {
|
|
description = "Fully qualified image URI for the web app (e.g. 12345.dkr.ecr.us-east-1.amazonaws.com/shared-memory-web:v0.5.0). Same image is reused for the migrator."
|
|
type = string
|
|
}
|
|
|
|
variable "embedder_image" {
|
|
description = "Fully qualified image URI for the embedder sidecar."
|
|
type = string
|
|
}
|
|
|
|
# -------- Database --------
|
|
|
|
variable "database_url" {
|
|
description = "Postgres connection URL, e.g. postgres://user:pw@host:5432/db. Stored in Secrets Manager. Host must be reachable from the private subnets."
|
|
type = string
|
|
sensitive = true
|
|
}
|
|
|
|
# -------- OIDC --------
|
|
|
|
variable "oidc_issuer" {
|
|
description = "OIDC issuer URL (matches `iss` claim). Both web and MCP clients must live at this issuer."
|
|
type = string
|
|
}
|
|
|
|
variable "oidc_client_id_web" {
|
|
description = "Confidential client ID for the Web UI."
|
|
type = string
|
|
}
|
|
|
|
variable "oidc_client_secret_web" {
|
|
description = "Confidential client secret for the Web UI. Stored in Secrets Manager."
|
|
type = string
|
|
sensitive = true
|
|
}
|
|
|
|
variable "oidc_client_id_mcp" {
|
|
description = "Public (PKCE) client ID used by Claude Code against /api/mcp."
|
|
type = string
|
|
}
|
|
|
|
variable "oidc_audience" {
|
|
description = "Expected `aud` claim on MCP access tokens. Typically 'shared-memory'."
|
|
type = string
|
|
}
|
|
|
|
# -------- App-level secrets --------
|
|
|
|
variable "nextauth_secret" {
|
|
description = "Session cookie signing key for Auth.js. Generate with `openssl rand -base64 32`."
|
|
type = string
|
|
sensitive = true
|
|
}
|
|
|
|
variable "cli_token_secret" {
|
|
description = "HMAC key used by /connect to mint long-lived CLI tokens."
|
|
type = string
|
|
sensitive = true
|
|
}
|
|
|
|
# -------- Embedder model knobs (rarely overridden) --------
|
|
|
|
variable "embedding_model" {
|
|
description = "Xenova/transformers model identifier the embedder downloads on cold start."
|
|
type = string
|
|
default = "Xenova/bge-small-en-v1.5"
|
|
}
|
|
|
|
variable "embedding_dim" {
|
|
description = "Output dimension of the chosen embedding model. Must match the pgvector column width."
|
|
type = number
|
|
default = 384
|
|
}
|
|
|
|
# -------- Fargate sizing --------
|
|
|
|
variable "app_cpu" {
|
|
description = "Fargate CPU units for the app task. 512 = 0.5 vCPU, 1024 = 1 vCPU."
|
|
type = number
|
|
default = 512
|
|
}
|
|
|
|
variable "app_memory" {
|
|
description = "Fargate memory (MiB) for the app task."
|
|
type = number
|
|
default = 1024
|
|
}
|
|
|
|
variable "app_desired_count" {
|
|
description = "Number of app task replicas."
|
|
type = number
|
|
default = 1
|
|
}
|
|
|
|
variable "embedder_cpu" {
|
|
description = "Fargate CPU units for the embedder. The model needs ~1 vCPU for tolerable latency."
|
|
type = number
|
|
default = 1024
|
|
}
|
|
|
|
variable "embedder_memory" {
|
|
description = "Fargate memory (MiB) for the embedder. 2 GiB is comfortable for bge-small."
|
|
type = number
|
|
default = 2048
|
|
}
|
|
|
|
variable "embedder_desired_count" {
|
|
description = "Number of embedder task replicas."
|
|
type = number
|
|
default = 1
|
|
}
|
|
|
|
variable "migrator_cpu" {
|
|
description = "Fargate CPU units for the one-shot migrator task."
|
|
type = number
|
|
default = 512
|
|
}
|
|
|
|
variable "migrator_memory" {
|
|
description = "Fargate memory (MiB) for the one-shot migrator task."
|
|
type = number
|
|
default = 1024
|
|
}
|
|
|
|
# -------- Observability / misc --------
|
|
|
|
variable "log_level" {
|
|
description = "LOG_LEVEL env var passed to app and embedder."
|
|
type = string
|
|
default = "info"
|
|
}
|
|
|
|
variable "log_retention_days" {
|
|
description = "CloudWatch retention applied to every log group the module creates."
|
|
type = number
|
|
default = 14
|
|
}
|
|
|
|
variable "tags" {
|
|
description = "Tags merged onto every resource the module creates."
|
|
type = map(string)
|
|
default = {}
|
|
}
|