surshar / claude-code
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
Built by Anthropic · github.com/anthropics
| 1 | # Inputs — mirror the env-overridable knobs in setup.sh (same defaults). |
| 2 | |
| 3 | variable "region" { |
| 4 | description = "AWS region for everything this module creates. Pick one where Bedrock serves the Claude models you need. (The Bedrock region the gateway calls is set separately inside gateway.yaml — keep the two equal.) The walkthrough is scoped to the commercial US regions (us-east-1/us-east-2/us-west-1/us-west-2 — GovCloud and ISO regions are different partitions); see allow_non_us_region." |
| 5 | type = string |
| 6 | default = "us-east-1" |
| 7 | } |
| 8 | |
| 9 | variable "allow_non_us_region" { |
| 10 | description = "The bedrock-invoke IAM policy and the gateway's built-in model catalog use the US-geo (us.anthropic.*) cross-region inference profiles, so any region outside the commercial US four (including GovCloud/ISO, which are different partitions) fails a plan-time precondition. Set true ONLY after pinning region-appropriate inference profiles via a models: block in gateway.yaml (see the config reference) and widening the ARN geo prefix in main.tf's bedrock-invoke policy." |
| 11 | type = bool |
| 12 | default = false |
| 13 | } |
| 14 | |
| 15 | # ── Networking inputs (prerequisites — NOT created here) ──────────────────── |
| 16 | variable "vpc_id" { |
| 17 | description = "Existing VPC ID (the walkthrough's prerequisite VPC). Unlike the GCP example, this module does not create the network." |
| 18 | type = string |
| 19 | } |
| 20 | |
| 21 | variable "private_subnet_ids" { |
| 22 | description = "Two+ private subnet IDs in different AZs, with outbound internet via a NAT gateway. The internal ALB, the ECS tasks, and the RDS subnet group all attach here." |
| 23 | type = list(string) |
| 24 | validation { |
| 25 | condition = length(var.private_subnet_ids) >= 2 |
| 26 | error_message = "private_subnet_ids needs at least two subnets in different AZs (the internal ALB requires two)." |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | variable "corporate_cidr" { |
| 31 | description = "Your corporate network CIDR — the only source the ALB security group admits on 443. Must not overlap private_subnet_ids: hosts there are trusted_proxies (gateway.yaml) and could spoof client IPs via X-Forwarded-For." |
| 32 | type = string |
| 33 | } |
| 34 | |
| 35 | # ── IAM (§2) ──────────────────────────────────────────────────────────────── |
| 36 | variable "task_role_name" { |
| 37 | description = "ECS task role name (the gateway's runtime identity; its only permission is Bedrock invoke)." |
| 38 | type = string |
| 39 | default = "claude-gateway-task" |
| 40 | } |
| 41 | |
| 42 | variable "execution_role_name" { |
| 43 | description = "ECS execution role name (the ECS agent's identity: pulls the image, injects the secrets)." |
| 44 | type = string |
| 45 | default = "claude-gateway-execution" |
| 46 | } |
| 47 | |
| 48 | # ── Image (§6) ────────────────────────────────────────────────────────────── |
| 49 | # Terraform creates the ECR repository but does NOT build/push the image (that's |
| 50 | # a docker build step — see README). It references the image by tag. |
| 51 | variable "ecr_repo" { |
| 52 | description = "ECR repository name." |
| 53 | type = string |
| 54 | default = "claude-gateway" |
| 55 | } |
| 56 | |
| 57 | variable "image_tag" { |
| 58 | description = "Image tag — the tag you built and pushed (must already exist in the repo as linux/amd64, with gateway.yaml baked in). setup.sh tags as <version>-cfg<sha8 of gateway.yaml>; see the README Deploy section for the build command." |
| 59 | type = string |
| 60 | validation { |
| 61 | condition = can(regex("^[A-Za-z0-9_][A-Za-z0-9._-]{0,127}$", var.image_tag)) |
| 62 | error_message = "image_tag must be a valid OCI tag — set it to the tag you pushed (the '<version>' in terraform.tfvars.example is a placeholder)." |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | variable "gateway_config_path" { |
| 67 | description = "Path to gateway.yaml. Empty = ../gateway.yaml relative to this module. Read for the REPLACE_ME guard and the config-sha that rolls the service; the file itself ships inside the image." |
| 68 | type = string |
| 69 | default = "" |
| 70 | } |
| 71 | |
| 72 | # ── RDS (§3) ──────────────────────────────────────────────────────────────── |
| 73 | variable "db_instance" { |
| 74 | description = "RDS instance identifier." |
| 75 | type = string |
| 76 | default = "claude-gateway-db" |
| 77 | } |
| 78 | |
| 79 | variable "db_engine_version" { |
| 80 | description = "Postgres major version. The gateway supports PostgreSQL 14 or newer; 16 is the recommended default." |
| 81 | type = string |
| 82 | default = "16" |
| 83 | } |
| 84 | |
| 85 | variable "db_instance_class" { |
| 86 | description = "RDS instance class." |
| 87 | type = string |
| 88 | default = "db.t4g.micro" |
| 89 | } |
| 90 | |
| 91 | variable "db_allocated_storage" { |
| 92 | description = "RDS allocated storage in GiB." |
| 93 | type = number |
| 94 | default = 20 |
| 95 | } |
| 96 | |
| 97 | variable "db_name" { |
| 98 | description = "Database name." |
| 99 | type = string |
| 100 | default = "claude_gateway" |
| 101 | } |
| 102 | |
| 103 | variable "db_user" { |
| 104 | description = "Database master user (the gateway connects as this role)." |
| 105 | type = string |
| 106 | default = "gateway" |
| 107 | } |
| 108 | |
| 109 | # ── Secrets (§5) ──────────────────────────────────────────────────────────── |
| 110 | # The execution role's secrets-read policy grants read on exactly these three |
| 111 | # secrets' ARNs, so renames are picked up automatically on the next apply. |
| 112 | variable "secret_name" { |
| 113 | description = "Secrets Manager secret holding the Postgres connection string." |
| 114 | type = string |
| 115 | default = "gateway-postgres-url" |
| 116 | } |
| 117 | |
| 118 | variable "jwt_secret_name" { |
| 119 | description = "Secrets Manager secret holding the session JWT signing key." |
| 120 | type = string |
| 121 | default = "gateway-jwt-secret" |
| 122 | } |
| 123 | |
| 124 | variable "oidc_secret_name" { |
| 125 | description = "Secrets Manager secret holding the Okta OIDC client secret." |
| 126 | type = string |
| 127 | default = "gateway-oidc-client-secret" |
| 128 | } |
| 129 | |
| 130 | variable "oidc_client_secret" { |
| 131 | description = "Okta OIDC client secret value. Leave empty to NOT manage the version via Terraform (only if you add the secret version out-of-band — without one the tasks fail to start)." |
| 132 | type = string |
| 133 | default = "" |
| 134 | sensitive = true |
| 135 | } |
| 136 | |
| 137 | # ── ECS + ALB (§7) ────────────────────────────────────────────────────────── |
| 138 | variable "cluster_name" { |
| 139 | description = "ECS cluster name." |
| 140 | type = string |
| 141 | default = "claude-gateway" |
| 142 | } |
| 143 | |
| 144 | variable "service_name" { |
| 145 | description = "ECS service name (also used for the ALB and target group)." |
| 146 | type = string |
| 147 | default = "claude-gateway" |
| 148 | } |
| 149 | |
| 150 | variable "log_group_name" { |
| 151 | description = "CloudWatch Logs group for the gateway's stderr (audit events + operational logs)." |
| 152 | type = string |
| 153 | default = "/ecs/claude-gateway" |
| 154 | } |
| 155 | |
| 156 | variable "log_retention_days" { |
| 157 | description = "CloudWatch Logs retention in days. The group carries the gateway's audit events, so align with your audit retention policy." |
| 158 | type = number |
| 159 | default = 90 |
| 160 | } |
| 161 | |
| 162 | variable "acm_certificate_arn" { |
| 163 | description = "ACM certificate ARN for the internal gateway hostname (the host in gateway.yaml's public_url), served by the ALB's HTTPS listener." |
| 164 | type = string |
| 165 | } |
| 166 | |
| 167 | variable "task_cpu" { |
| 168 | description = "Fargate task CPU units." |
| 169 | type = number |
| 170 | default = 1024 |
| 171 | } |
| 172 | |
| 173 | variable "task_memory" { |
| 174 | description = "Fargate task memory (MiB)." |
| 175 | type = number |
| 176 | default = 2048 |
| 177 | } |
| 178 | |
| 179 | variable "desired_count" { |
| 180 | description = "ECS service desired task count. Each task opens a Postgres pool of up to 5 connections (the gateway's store.max_connections default) and db.t4g.micro caps at ~80 max_connections — keep desired_count × 5 below the DB class's limit, or raise the class before raising this." |
| 181 | type = number |
| 182 | default = 1 |
| 183 | } |
| 184 | |
| 185 | variable "deletion_protection" { |
| 186 | description = "Deletion protection on RDS and the ALB (and whether RDS skips the final snapshot on destroy). Keep true to avoid accidental deletion of the running deployment." |
| 187 | type = bool |
| 188 | default = true |
| 189 | } |