AWS Application Load Balancer (ALB) Setup
This guide covers deploying Gordon behind AWS Application Load Balancer for TLS termination.
Overview
AWS ALB is a Layer 7 load balancer that:
- Terminates TLS connections
- Forwards requests to your EC2 instances or ECS containers
- Automatically scales with traffic
- Sets
X-Forwarded-Forheader with the client's real IP
Architecture
Client → ALB (HTTPS/443) → Gordon (HTTP/80) → Containers
↓
TLS terminated
X-Forwarded-For set
Understanding VPC CIDR
A VPC (Virtual Private Cloud) is your isolated network in AWS. Every VPC has a CIDR (Classless Inter-Domain Routing) block—the private IP range used by resources in that VPC.
ALB connects to Gordon from within your VPC, so Gordon sees the ALB's private IP, not the client's public IP. The client IP is passed via X-Forwarded-For.
To find your VPC CIDR:
- Go to AWS Console → VPC → Your VPCs
- Find the IPv4 CIDR column
- Common values:
10.0.0.0/16,172.31.0.0/16
Gordon Configuration
[api.rate_limit]
enabled = true
# Trust your VPC CIDR so Gordon reads X-Forwarded-For from ALB
trusted_proxies = ["10.0.0.0/16"] # Replace with your VPC CIDR
Multiple VPCs or Subnets
If Gordon receives traffic from multiple VPCs (e.g., via VPC peering):
[api.rate_limit]
trusted_proxies = [
"10.0.0.0/16", # Production VPC
"10.1.0.0/16", # Staging VPC
]
ALB Configuration
Target Group Settings
When creating your ALB target group:
| Setting | Value |
|---|---|
| Target type | instance or ip |
| Protocol | HTTP |
| Port | 80 (or your Gordon port) |
| Health check path | /health or /v2/ |
Client IP Preservation
ALB automatically sets X-Forwarded-For. No special configuration needed for HTTP targets.
For NLB (Network Load Balancer) with TCP, you may need to enable Proxy Protocol v2:
# Kubernetes annotation for AWS Load Balancer Controller
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
Verifying the Setup
- Make a request through the ALB
- Check Gordon logs for the client IP:
# Should show real client IP, not ALB IP
journalctl -u gordon | grep "client_ip"
If you see the ALB's private IP (e.g., 10.0.x.x) instead of the client's public IP, check that:
trusted_proxiesincludes your VPC CIDR- ALB is forwarding
X-Forwarded-For(default behavior)
Security Groups
Ensure your security groups allow:
| Source | Destination | Port | Purpose |
|---|---|---|---|
0.0.0.0/0 |
ALB | 443 | HTTPS from internet |
| ALB SG | Gordon SG | 80 | ALB to Gordon |
Terraform Example
resource "aws_lb" "gordon" {
name = "gordon-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = var.public_subnets
}
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.gordon.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = var.certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.gordon.arn
}
}
resource "aws_lb_target_group" "gordon" {
name = "gordon-tg"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
health_check {
path = "/v2/"
healthy_threshold = 2
unhealthy_threshold = 10
}
}
Troubleshooting
All requests show the same IP
Symptom: Rate limiting doesn't work, logs show ALB IP for all requests.
Cause: trusted_proxies doesn't include ALB's IP range.
Fix: Add your VPC CIDR to trusted_proxies.
502 Bad Gateway
Symptom: ALB returns 502 errors.
Cause: Gordon health check failing or not listening.
Fix: Verify Gordon is running and health check path is correct.