hearth/terraform/modules/nlb/main.tf
Eric Garcia e78000831e Initial commit: Port infrastructure from coherence-mcp
Hearth is the infrastructure home for the letemcook ecosystem.

Ported from coherence-mcp/infra:
- Terraform modules (VPC, EKS, IAM, NLB, S3, storage)
- Kubernetes manifests (Forgejo, ingress, cert-manager, karpenter)
- Deployment scripts (phased rollout)

Status: Not deployed. EKS cluster needs to be provisioned.

Next steps:
1. Bootstrap terraform backend
2. Deploy phase 1 (foundation)
3. Deploy phase 2 (core services including Forgejo)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:06:13 -05:00

294 lines
6.6 KiB
HCL

# NLB Module - Shared Network Load Balancer
# RFC 0039: ADR-Compliant Foundation Infrastructure
#
# Architecture:
# - Single shared NLB for all services (~$16/mo)
# - Ports: 53 (DNS), 25/587/993 (Email), 443 (HTTPS)
# - Cross-zone load balancing enabled
# - Target groups for each service type
# Network Load Balancer
# RFC 0046: Domain Email Migration - Elastic IP support for stable glue records
resource "aws_lb" "main" {
name = var.name
internal = false
load_balancer_type = "network"
# Use subnet_mapping with Elastic IPs when enabled (for DNS glue records)
# Otherwise use simple subnets assignment
dynamic "subnet_mapping" {
for_each = var.enable_static_ips ? zipmap(var.public_subnet_ids, var.elastic_ip_ids) : {}
content {
subnet_id = subnet_mapping.key
allocation_id = subnet_mapping.value
}
}
# Fallback to simple subnets when not using static IPs
subnets = var.enable_static_ips ? null : var.public_subnet_ids
enable_cross_zone_load_balancing = true
enable_deletion_protection = var.enable_deletion_protection
tags = merge(var.tags, {
Name = var.name
})
}
# Target Group for HTTPS (443) - Routes to ALB Ingress Controller
resource "aws_lb_target_group" "https" {
name = "${var.name}-https"
port = 443
protocol = "TCP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
protocol = "TCP"
port = "traffic-port"
healthy_threshold = 3
unhealthy_threshold = 3
interval = 30
}
tags = merge(var.tags, {
Name = "${var.name}-https"
Service = "ingress"
})
}
# Listener for HTTPS (443)
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "TCP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.https.arn
}
tags = var.tags
}
# Target Group for DNS UDP (53)
resource "aws_lb_target_group" "dns_udp" {
name = "${var.name}-dns-udp"
port = 53
protocol = "UDP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
protocol = "TCP"
port = 53
healthy_threshold = 3
unhealthy_threshold = 3
interval = 30
}
tags = merge(var.tags, {
Name = "${var.name}-dns-udp"
Service = "dns"
})
}
# Listener for DNS UDP (53)
resource "aws_lb_listener" "dns_udp" {
load_balancer_arn = aws_lb.main.arn
port = 53
protocol = "UDP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.dns_udp.arn
}
tags = var.tags
}
# Target Group for DNS TCP (53)
resource "aws_lb_target_group" "dns_tcp" {
name = "${var.name}-dns-tcp"
port = 53
protocol = "TCP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
protocol = "TCP"
port = "traffic-port"
healthy_threshold = 3
unhealthy_threshold = 3
interval = 30
}
tags = merge(var.tags, {
Name = "${var.name}-dns-tcp"
Service = "dns"
})
}
# Listener for DNS TCP (53)
resource "aws_lb_listener" "dns_tcp" {
load_balancer_arn = aws_lb.main.arn
port = 53
protocol = "TCP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.dns_tcp.arn
}
tags = var.tags
}
# Target Group for SMTP (25)
resource "aws_lb_target_group" "smtp" {
name = "${var.name}-smtp"
port = 25
protocol = "TCP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
protocol = "TCP"
port = "traffic-port"
healthy_threshold = 3
unhealthy_threshold = 3
interval = 30
}
tags = merge(var.tags, {
Name = "${var.name}-smtp"
Service = "email"
})
}
# Listener for SMTP (25)
resource "aws_lb_listener" "smtp" {
load_balancer_arn = aws_lb.main.arn
port = 25
protocol = "TCP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.smtp.arn
}
tags = var.tags
}
# Target Group for Email Submission (587)
resource "aws_lb_target_group" "submission" {
name = "${var.name}-submission"
port = 587
protocol = "TCP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
protocol = "TCP"
port = "traffic-port"
healthy_threshold = 3
unhealthy_threshold = 3
interval = 30
}
tags = merge(var.tags, {
Name = "${var.name}-submission"
Service = "email"
})
}
# Listener for Email Submission (587)
resource "aws_lb_listener" "submission" {
load_balancer_arn = aws_lb.main.arn
port = 587
protocol = "TCP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.submission.arn
}
tags = var.tags
}
# Target Group for IMAPS (993)
resource "aws_lb_target_group" "imaps" {
name = "${var.name}-imaps"
port = 993
protocol = "TCP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
protocol = "TCP"
port = "traffic-port"
healthy_threshold = 3
unhealthy_threshold = 3
interval = 30
}
tags = merge(var.tags, {
Name = "${var.name}-imaps"
Service = "email"
})
}
# Listener for IMAPS (993)
resource "aws_lb_listener" "imaps" {
load_balancer_arn = aws_lb.main.arn
port = 993
protocol = "TCP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.imaps.arn
}
tags = var.tags
}
# HTTP Listener (80) - Redirect to HTTPS
resource "aws_lb_target_group" "http" {
name = "${var.name}-http"
port = 80
protocol = "TCP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
protocol = "TCP"
port = "traffic-port"
healthy_threshold = 3
unhealthy_threshold = 3
interval = 30
}
tags = merge(var.tags, {
Name = "${var.name}-http"
Service = "ingress"
})
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.main.arn
port = 80
protocol = "TCP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.http.arn
}
tags = var.tags
}