Host-Based Routing with AWS ALB and Terraform – Secure Multi-App Access by Domain

In Part 4, we configured Path-Based Routing using Terraform to forward traffic based on URL paths like /app1
and /app2
.
Now in Part 5, we enhance that setup by switching to Host Header-Based Routing, which allows you to route requests based on subdomains like:
app1.rezaops.com
→ App 1 backendapp2.rezaops.com
→ App 2 backend
This method is ideal for hosting multiple services or environments behind a single ALB using clean, production-style URLs.
🔁 What Did We Change From the Previous Setup?
We’re still using the same ALB module, but we updated the HTTPS listener rules. Instead of checking for paths, we now check for host headers.
Here’s the updated configuration, with key differences explained.
🔧 ALB Module Overview (No Structural Changes)
module "alb" {
source = "terraform-aws-modules/alb/aws"
version = "9.11.0"
name = "${local.name}-alb"
load_balancer_type = "application"
vpc_id = module.vpc.vpc_id
subnets = module.vpc.public_subnets
security_groups = [module.loadbalancer_sg.security_group_id]
enable_deletion_protection = false
✅ Same as before – we’re deploying an ALB in public subnets with HTTP and HTTPS access.
🔒 HTTP to HTTPS Redirect (Still Present)
my-http-https-redirect = {
port = 80
protocol = "HTTP"
redirect = {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
✅ Ensures all HTTP requests are redirected to HTTPS — no change here.
🧭 Updated HTTPS Listener – Host Header Based Routing
🔁 Before (Part 3):
path_pattern = {
values = ["/app1*"]
}
🔄 Now (Part 4):
We use host_header instead of path patterns:
my-https-listener = {
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-Res-2021-06"
certificate_arn = module.acm.acm_certificate_arn
fixed_response = {
content_type = "text/plain"
message_body = "Fixed Static message - for Root Context"
status_code = "200"
}
rules = {
myapp1-rule = {
actions = [{
type = "weighted-forward"
target_groups = [{ target_group_key = "mytg1", weight = 1 }]
stickiness = { enabled = true, duration = 3600 }
}]
conditions = [{
host_header = {
values = [var.app1_dns_name]
}
}]
},
myapp2-rule = {
actions = [{
type = "weighted-forward"
target_groups = [{ target_group_key = "mytg2", weight = 1 }]
stickiness = { enabled = true, duration = 3600 }
}]
conditions = [{
host_header = {
values = [var.app2_dns_name]
}
}]
}
}
}
🔍 Explanation:
- host_header: Matches requests based on the host field in the HTTP request header.
- var.app1_dns_name / var.app2_dns_name: These should be set to
app1.rezaops.com
andapp2.rezaops.com
in your variables. - stickiness: ALB cookie-based stickiness still enabled.
- weighted-forward: Each rule forwards traffic to its respective target group (
mytg1
ormytg2
).
🎯 Target Groups (No Change Here)
Target groups mytg1
and mytg2
remain the same. Each group listens on port 80 and includes its own health check:
mytg1 = {
name_prefix = "mytg1-"
port = 80
protocol = "HTTP"
target_type = "instance"
health_check = {
path = "/app1/index.html"
matcher = "200-399"
}
...
}
mytg2 = {
name_prefix = "mytg2-"
port = 80
protocol = "HTTP"
target_type = "instance"
health_check = {
path = "/app2/index.html"
matcher = "200-399"
}
...
}
✅ Each app has its own health check path and group of EC2 instances.
🔗 EC2 Target Group Attachments
Also unchanged. We’re manually attaching the EC2s for App 1 and App 2:
resource "aws_lb_target_group_attachment" "mytg1" {
for_each = { for k, v in module.ec2_private_app1 : k => v }
target_group_arn = module.alb.target_groups["mytg1"].arn
target_id = each.value.id
port = 80
}
resource "aws_lb_target_group_attachment" "mytg2" {
for_each = { for k, v in module.ec2_private_app2 : k => v }
target_group_arn = module.alb.target_groups["mytg2"].arn
target_id = each.value.id
port = 80
}
✅ Summary
In this post, we updated our existing ALB setup to support Host-Based Routing instead of Path-Based. This setup is perfect when:
- You want clean subdomain URLs (
app1.example.com
,app2.example.com
) - You need to serve multiple apps under the same ALB using DNS rules
- You want to build toward microservices or multi-tenant architectures
You’ve now built an ALB that handles:
- HTTPS redirection
- TLS with ACM
- Listener rules using Host Headers
- DNS aliasing with Route 53
- Backend registration by EC2 group