Ctrl K
ComunidadGuías…

gateway/infra/terraform/main.tf

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# OpenCompany Gateway: BerriAI's official LiteLLM module on ECS Fargate, plus
# the few things the module leaves to the caller (TLS certificate, DNS record,
# the salt key, and the vendor-key secrets).

locals {
  # Keep in step with the module version below, the image tag in
  # gateway/local/docker-compose.yml and LITELLM_VERSION in the CI workflow
  # (gateway/tests/test_pins.py checks). 1.103.x is the only stable line with
  # the streamed-alias billing fix (LiteLLM PR #44341).
  litellm_version = "1.103.4"
  name            = "opencompany-gateway-${var.env}"

  common_env = {
    LITELLM_MODE   = "PRODUCTION"
    LITELLM_LOG    = "ERROR"
    PROXY_BASE_URL = "https://${var.gateway_hostname}"
    NO_DOCS        = "True"
    NO_REDOC       = "True"
    NO_OPENAPI     = "True"
    # Prices come from this reviewed copy of LiteLLM's price list. Without it
    # the gateway downloads upstream main on every start (prices change
    # unannounced), and its bundled list predates the current models.
    LITELLM_MODEL_COST_MAP_URL = "https://raw.githubusercontent.com/BerriAI/litellm/729b02d05719715f4faeb1f81ef2728ef06c3273/model_prices_and_context_window.json"
  }

  # Creates the two SpendLogs indexes that LiteLLM stopped creating in
  # migrations (1.103.3+). Runs as the app user, which owns the tables.
  spendlogs_index_sql = <<-SQL
    GRANT litellm_app TO postgres;
    SET ROLE litellm_app;
    CREATE INDEX CONCURRENTLY IF NOT EXISTS "LiteLLM_SpendLogs_api_key_startTime_idx" ON "LiteLLM_SpendLogs" ("api_key", "startTime");
    CREATE INDEX CONCURRENTLY IF NOT EXISTS "LiteLLM_SpendLogs_litellm_call_id_idx" ON "LiteLLM_SpendLogs" ("litellm_call_id");
  SQL
}

# LITELLM_SALT_KEY encrypts provider credentials stored in the database. It can
# never change once a credential is stored, so it is generated once and kept.
resource "random_password" "salt_key" {
  length  = 48
  special = false
}

resource "aws_secretsmanager_secret" "salt_key" {
  name                    = "${local.name}/litellm-salt-key"
  description             = "LITELLM_SALT_KEY for the gateway and backend. Never change it."
  recovery_window_in_days = 30
}

resource "aws_secretsmanager_secret_version" "salt_key" {
  secret_id     = aws_secretsmanager_secret.salt_key.id
  secret_string = random_password.salt_key.result

  lifecycle {
    ignore_changes = [secret_string]
  }
}

# One empty secret per vendor key. Values are set out of band (see README),
# so no vendor key ever passes through Terraform state.
resource "aws_secretsmanager_secret" "vendor" {
  for_each = toset(var.secret_env_names)

  name                    = "${local.name}/env/${lower(replace(each.value, "_", "-"))}"
  description             = "${each.value} for the gateway service."
  recovery_window_in_days = 7
}

module "litellm" {
  source  = "BerriAI/litellm/aws"
  version = "1.103.4"

  region = var.region
  tenant = "opencompany"
  env    = var.env
  azs    = var.azs

  gateway_image    = "ghcr.io/berriai/litellm-gateway:v${local.litellm_version}"
  backend_image    = "ghcr.io/berriai/litellm-backend:v${local.litellm_version}"
  ui_image         = "ghcr.io/berriai/litellm-ui:v${local.litellm_version}"
  migrations_image = "ghcr.io/berriai/litellm-migrations:v${local.litellm_version}"

  acm_certificate_arn = aws_acm_certificate_validation.gateway.certificate_arn

  gateway_desired_count = var.gateway_min_tasks
  gateway_min_capacity  = var.gateway_min_tasks
  gateway_max_capacity  = var.gateway_max_tasks
  gateway_cpu_target    = 60
  # Never scale on memory: Prisma's query engine holds on to its peak.
  gateway_memory_target = 0
  # In-task PgBouncer caps each task's database connections.
  gateway_connection_pool_enabled = true

  proxy_config = yamldecode(file("${path.module}/../../litellm/config.yaml"))

  gateway_extra_secrets = merge(
    { for env_name, secret in aws_secretsmanager_secret.vendor : env_name => secret.arn },
    { LITELLM_SALT_KEY = aws_secretsmanager_secret.salt_key.arn },
  )
  backend_extra_secrets = {
    LITELLM_SALT_KEY = aws_secretsmanager_secret.salt_key.arn
  }
  gateway_extra_env = local.common_env
  backend_extra_env = local.common_env

  depends_on = [aws_secretsmanager_secret_version.salt_key]
}

# TLS certificate for the gateway hostname, validated through DNS.
resource "aws_acm_certificate" "gateway" {
  domain_name       = var.gateway_hostname
  validation_method = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "gateway_cert_validation" {
  for_each = {
    for option in aws_acm_certificate.gateway.domain_validation_options : option.domain_name => option
  }

  zone_id         = var.route53_zone_id
  name            = each.value.resource_record_name
  type            = each.value.resource_record_type
  records         = [each.value.resource_record_value]
  ttl             = 60
  allow_overwrite = true
}

resource "aws_acm_certificate_validation" "gateway" {
  certificate_arn         = aws_acm_certificate.gateway.arn
  validation_record_fqdns = [for record in aws_route53_record.gateway_cert_validation : record.fqdn]
}

resource "aws_route53_record" "gateway" {
  zone_id = var.route53_zone_id
  name    = var.gateway_hostname
  type    = "CNAME"
  ttl     = 60
  records = [module.litellm.alb_dns_name]
}