Files
Claude-Code-Monitor/deployments/terraform/modules/loadbalancer/main.tf
T
nntrivi2001 57dc91585d feat: Claude Code Monitor — lanes, pipelines and a merged workspace
Internal SmartGift build of a Claude Code monitoring dashboard.

Lanes: a durable unit of parallel agent work, one per working directory,
tracked across session restarts. Managed lanes are git worktrees the
dashboard provisions and can reset or remove behind a three-check destroy
guard and a counted preflight; adopted lanes are directories you already
own and are never destroyable.

Pipelines: a lane moves through pipeline stages. A stage the agent declares
with evidence renders green; a stage inferred from the tool-event stream
renders dashed amber and never counts as done. Detection is forward-only
within a 30-minute window, and never writes the declared stage.

Workspace: one page at /run with a lane grid, the selected lane's pipeline,
and a full Claude console behind a disclosure.
2026-07-30 14:39:03 +07:00

248 lines
8.5 KiB
Terraform
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ─────────────────────────────────────────────────────────────────────────────
# Load Balancer module Application load balancer with WebSocket support
#
# Provisions:
# - ALB in public subnets
# - HTTPS listener with TLS termination
# - HTTP → HTTPS redirect
# - Weighted target groups for blue/green and canary deployments
# - Sticky sessions for WebSocket connections
# - Path-based routing for MCP sidecar (/mcp/*)
# - Health checks at /api/health
# ─────────────────────────────────────────────────────────────────────────────
# Production TLS enforcement — prevents deploying production without encryption
check "production_tls_required" {
assert {
condition = var.environment != "production" || var.tls_certificate_arn != ""
error_message = "Production deployments require TLS. Set tls_certificate_arn and domain_name."
}
}
check "production_domain_required" {
assert {
condition = var.environment != "production" || var.domain_name != ""
error_message = "Production deployments require a domain name. Set domain_name."
}
}
locals {
name_prefix = lower(replace("${var.project_name}-${var.environment}", "_", "-"))
# Determine whether TLS is configured
has_tls = var.tls_certificate_arn != ""
common_tags = merge(
{
module = "loadbalancer"
},
var.tags,
)
}
# ─────────────────────────────────────────────────────────────────────────────
# Application Load Balancer
# ─────────────────────────────────────────────────────────────────────────────
resource "aws_lb" "main" {
name = "${local.name_prefix}-alb"
internal = false
load_balancer_type = "application"
security_groups = var.security_group_ids
subnets = var.public_subnet_ids
enable_deletion_protection = var.environment == "production" ? true : var.enable_deletion_protection
enable_http2 = true
idle_timeout = 300 # WebSocket connections may be long-lived
drop_invalid_header_fields = true
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-alb"
})
lifecycle {
prevent_destroy = false
# For production, set enable_deletion_protection = true above (enforced automatically)
}
}
# ─────────────────────────────────────────────────────────────────────────────
# HTTPS listener (primary with weighted target groups for blue/green)
# ─────────────────────────────────────────────────────────────────────────────
resource "aws_lb_listener" "https" {
count = local.has_tls ? 1 : 0
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = var.tls_certificate_arn
default_action {
type = "forward"
forward {
target_group {
arn = var.blue_target_group_arn
weight = var.blue_weight
}
target_group {
arn = var.green_target_group_arn
weight = var.green_weight
}
stickiness {
enabled = true
duration = 86400
}
}
}
tags = local.common_tags
}
# ─────────────────────────────────────────────────────────────────────────────
# HTTP listener redirect to HTTPS when TLS is configured, else forward
# ─────────────────────────────────────────────────────────────────────────────
resource "aws_lb_listener" "http_redirect" {
count = local.has_tls ? 1 : 0
load_balancer_arn = aws_lb.main.arn
port = 80
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
tags = local.common_tags
}
resource "aws_lb_listener" "http_forward" {
count = local.has_tls ? 0 : 1
load_balancer_arn = aws_lb.main.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
forward {
target_group {
arn = var.blue_target_group_arn
weight = var.blue_weight
}
target_group {
arn = var.green_target_group_arn
weight = var.green_weight
}
stickiness {
enabled = true
duration = 86400
}
}
}
tags = local.common_tags
}
# ─────────────────────────────────────────────────────────────────────────────
# MCP sidecar target group
# ─────────────────────────────────────────────────────────────────────────────
resource "aws_lb_target_group" "mcp" {
name_prefix = "mcp-"
port = var.mcp_port
protocol = "HTTP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
path = "/"
port = tostring(var.mcp_port)
protocol = "HTTP"
healthy_threshold = var.health_check_healthy_threshold
unhealthy_threshold = var.health_check_unhealthy_threshold
timeout = var.health_check_timeout
interval = var.health_check_interval
matcher = "200-404"
}
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-mcp-tg"
})
lifecycle {
create_before_destroy = true
}
}
# ─────────────────────────────────────────────────────────────────────────────
# Path-based routing rule for MCP sidecar (/mcp/*)
# ─────────────────────────────────────────────────────────────────────────────
resource "aws_lb_listener_rule" "mcp_https" {
count = local.has_tls ? 1 : 0
listener_arn = aws_lb_listener.https[0].arn
priority = 10
action {
type = "forward"
target_group_arn = aws_lb_target_group.mcp.arn
}
condition {
path_pattern {
values = ["/mcp", "/mcp/*"]
}
}
tags = local.common_tags
}
resource "aws_lb_listener_rule" "mcp_http" {
count = local.has_tls ? 0 : 1
listener_arn = aws_lb_listener.http_forward[0].arn
priority = 10
action {
type = "forward"
target_group_arn = aws_lb_target_group.mcp.arn
}
condition {
path_pattern {
values = ["/mcp", "/mcp/*"]
}
}
tags = local.common_tags
}
# ─────────────────────────────────────────────────────────────────────────────
# Weight sum validation
# ─────────────────────────────────────────────────────────────────────────────
check "lb_weight_sum" {
assert {
condition = var.blue_weight + var.green_weight == 100
error_message = "blue_weight (${var.blue_weight}) + green_weight (${var.green_weight}) must sum to 100 for correct traffic routing."
}
}