Secure Your Apps with ALB Path-Based Routing and HTTPS using Terraform
In our previous setup, we created a secure VPC, launched EC2 instances, and added a basic Application Load Balancer (ALB).
This time, I was exploring Terraform on AWS and learned how to make my ALB more secure and professional.
Here is what we did step by step:
- Add TLS/SSL using AWS ACM (Certificate Manager)
- Create HTTPS listeners
- Route traffic based on URL paths like
/app1and/app2 - Attach multiple EC2 groups to the ALB
- Add DNS records with Route 53
1. ACM Module – TLS Certificate for HTTPS
We use the ACM module from Terraform Registry to create SSL certificates.
module "acm" {
source = "terraform-aws-modules/acm/aws"
version = "5.1.0"
domain_name = trimsuffix(data.aws_route53_zone.mydomain.name, ".")
zone_id = data.aws_route53_zone.mydomain.zone_id
subject_alternative_names = ["*.rezaops.com"]
validation_method = "DNS"
wait_for_validation = true
tags = local.common_tags
}
Explanation:
domain_name: Main domain for the certificate.zone_id: Your Route 53 hosted zone ID.subject_alternative_names: Adds a wildcard for subdomains.validation_method: Uses DNS for easy validation.wait_for_validation: Waits until the cert is ready.
Then we output the certificate ARN:
output "acm_certificate_arn" {
value = module.acm.acm_certificate_arn
}
2. ALB Module – Application Load Balancer Setup
We use the ALB module to create listeners, target groups, and routing rules.
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
}
Explanation:
- Deploys the ALB inside your VPC.
- Uses public subnets.
- Security group allows HTTP (80) and HTTPS (443).
3. HTTP → HTTPS Redirect
Redirects all traffic from HTTP to HTTPS.
my-http-https-redirect = {
port = 80
protocol = "HTTP"
redirect = {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
Explanation:
- Moves all insecure HTTP traffic to HTTPS for safety.
4. HTTPS Listener and Path-Based Routing
my-https-listener = {
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-Res-2021-06"
certificate_arn = module.acm.acm_certificate_arn
}
This listens on port 443 using the SSL certificate.
We also add routing rules:
Rule for /app1
myapp1-rule = {
actions = [{
type = "weighted-forward"
target_groups = [{
target_group_key = "mytg1"
weight = 1
}]
stickiness = {
enabled = true
duration = 3600
}
}]
conditions = [{
path_pattern = { values = ["/app1*"] }
}]
}
Same logic for /app2 but with a different target group.
5. Target Groups
mytg1 = {
create_attachment = false
port = 80
protocol = "HTTP"
health_check = {
enabled = true
path = "/app1/index.html"
matcher = "200-399"
}
tags = local.common_tags
}
Explanation:
- Target groups define which EC2s receive the traffic.
- Health checks keep your apps healthy.
6. Route 53 DNS Record
resource "aws_route53_record" "apps_dns" {
zone_id = data.aws_route53_zone.mydomain.zone_id
name = "apps.rezaops.com"
type = "A"
alias {
name = module.alb.dns_name
zone_id = module.alb.zone_id
evaluate_target_health = true
}
}
Explanation:
This connects your ALB to your domain name using Route 53.
Wrapping Up
In this guide, I learned how to:
- Get a TLS certificate using AWS ACM
- Redirect HTTP to HTTPS
- Add path-based routing for multiple apps
- Attach EC2 instances to target groups
- Connect everything with Route 53
This setup helps run several apps securely under one domain — great for small projects or learning environments.
Next Steps
Next, I plan to explore Host Header-Based Routing to route traffic using subdomains like app1.rezaops.com and app2.rezaops.com.