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>
294 lines
6.6 KiB
HCL
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
|
|
}
|