# 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 }