How I Used Terraform to Set Up Host-Based Routing on AWS ALB
Before this, we built an ALB setup using Terraform that used Path-Based Routing. This time, I was exploring Terraform on AWS and learned how to route traffic using Host-Based Routing.
This method lets us send traffic to different apps based on the subdomain instead of the URL path. For example:
app1.rezaops.com→ goes to App 1 backendapp2.rezaops.com→ goes to App 2 backend
It’s useful when you want to host more than one service under the same ALB but use clean, domain-based URLs.
What Changed from the Previous Setup
We are still using the same ALB module, but now we check for host headers instead of URL paths in our HTTPS listener rules.
ALB Module
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
}
This keeps our ALB in public subnets with HTTP and HTTPS access.
HTTP to HTTPS Redirect
my-http-https-redirect = {
port = 80
protocol = "HTTP"
redirect = {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
This still redirects all HTTP requests to HTTPS.
HTTPS Listener (Now Using Host Header)
We now use host_header instead of path_pattern:
my-https-listener = {
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-Res-2021-06"
certificate_arn = module.acm.acm_certificate_arn
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 (Simple):
host_header: Matches requests by subdomain (like app1.rezaops.com).var.app1_dns_nameandvar.app2_dns_name: store those domain names.stickiness: keeps users on the same target for a time.weighted-forward: sends traffic to the correct target group.
Target Groups
Each app has its own target group and 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 checks its own health path and uses its own EC2 instances.
EC2 Attachments
We also attach the EC2 instances manually to each target group:
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
}
This connects each EC2 instance to the right target group.
Summary
In this setup, we learned how to use Host-Based Routing with Terraform and AWS ALB.
Now, our load balancer supports:
- HTTPS redirection
- TLS/SSL with ACM
- Subdomain-based routing
- DNS integration with Route 53
- EC2 group backend attachments
This is a good step if you want to host several apps or services using one ALB in a simple and secure way.