Skip to content

AWS ALB Context Path based Routing using Terraform

Step-00: Pre-requisites

  • You need a Registered Domain in AWS Route53 to implement this usecase
  • Lets discuss more about it
  • Go to AWS Services -> Route53 -> Domains -> Registered Domains -> Register Domain
  • Choose a domain name: abcabc.com and click on Check
  • If available, click on Add to Cart and Click on Continue
  • Provide Contact Details for Your 1 Domain and Click on Continue
  • Terms and Conditions: Check and click on Complete Order
  • Go back to Billing and complete the payment for the domain to be approved
  • Copy your terraform-key.pem file to terraform-manifests/private-key folder

Step-01: Introduction

  • We are going to implement Context Path based Routing in AWS Application Load Balancer using Terraform.
  • To achieve that we are going to implement many series of steps.
  • Our core focus in the entire section should be primarily targeted to two things
  • Listener Indexes: https_listener_index = 0
  • Target Group Indexes: target_group_index = 0
  • If we are good with understanding these indexes and how to reference them, we are good with handling these multiple context paths or multiple header based routes or anything from ALB perspective.
  • We are going to implement the following using AWS ALB
  • Fixed Response for /* : http://apps.devopsincloud.com
  • App1 /app1* goes to App1 EC2 Instances: http://apps.devopsincloud.com/app1/index.html
  • App2 /app2* goes to App2 EC2 Instances: http://apps.devopsincloud.com/app2/index.html
  • HTTP to HTTPS Redirect

Step-02: Copy all files from previous section

  • We are going to copy all files from previous section 09-AWS-ALB-Application-LoadBalancer-Basic
  • Files from c1 to c10
  • Create new files
  • c6-02-datasource-route53-zone.tf
  • c11-acm-certificatemanager.tf
  • c12-route53-dnsregistration.tf
  • Review the files
  • app1-install.sh
  • app2-install.sh

Step-03: c5-05-securitygroup-loadbalancersg.tf

  • Update load balancer security group to allow port 443
      ingress_rules = ["http-80-tcp", "https-443-tcp"]
    

Step-04: c6-02-datasource-route53-zone.tf

  • Define the datasource for Route53 Zone
    # Get DNS information from AWS Route53
    data "aws_route53_zone" "mydomain" {
      name = "devopsincloud.com"
    }
    
    # Output MyDomain Zone ID
    output "mydomain_zoneid" {
      description = "The Hosted Zone id of the desired Hosted Zone"
      value = data.aws_route53_zone.mydomain.zone_id
    }
    

Step-05: c7-04-ec2instance-private-app1.tf

  • We will change the module name from ec2_private to ec2_private_app1
  • We will change the name to "${var.environment}-app1"
    # EC2 Instances that will be created in VPC Private Subnets for App1
    module "ec2_private_app1" {
      depends_on = [ module.vpc ] # VERY VERY IMPORTANT else userdata webserver provisioning will fail
      source  = "terraform-aws-modules/ec2-instance/aws"
      version = "2.17.0"
      # insert the 10 required variables here
      name                   = "${var.environment}-app1"
      ami                    = data.aws_ami.amzlinux2.id
      instance_type          = var.instance_type
      key_name               = var.instance_keypair
      #monitoring             = true
      vpc_security_group_ids = [module.private_sg.this_security_group_id]
      #subnet_id              = module.vpc.public_subnets[0]  
      subnet_ids = [
        module.vpc.private_subnets[0],
        module.vpc.private_subnets[1]
      ]  
      instance_count         = var.private_instance_count
      user_data = file("${path.module}/app1-install.sh")
      tags = local.common_tags
    }
    

Step-06: c7-05-ec2instance-private-app2.tf

  • Create new EC2 Instances for App2 Application
  • Module Name: ec2_private_app2
  • Name: "${var.environment}-app2"
  • User Data: user_data = file("${path.module}/app2-install.sh")
    # AWS EC2 Instance Terraform Module
    # EC2 Instances that will be created in VPC Private Subnets for App2
    module "ec2_private_app2" {
      depends_on = [ module.vpc ] # VERY VERY IMPORTANT else userdata webserver provisioning will fail
      source  = "terraform-aws-modules/ec2-instance/aws"
      version = "2.17.0"
      # insert the 10 required variables here
      name                   = "${var.environment}-app2"
      ami                    = data.aws_ami.amzlinux2.id
      instance_type          = var.instance_type
      key_name               = var.instance_keypair
      #monitoring             = true
      vpc_security_group_ids = [module.private_sg.this_security_group_id]
      #subnet_id              = module.vpc.public_subnets[0]  
      subnet_ids = [
        module.vpc.private_subnets[0],
        module.vpc.private_subnets[1]
      ]  
      instance_count         = var.private_instance_count
      user_data = file("${path.module}/app2-install.sh")
      tags = local.common_tags
    }
    

Step-07: c7-02-ec2instance-outputs.tf

  • Update App1 and App2 Outputs based on new module names
    # App1 - Private EC2 Instances
    ## ec2_private_instance_ids
    output "app1_ec2_private_instance_ids" {
      description = "List of IDs of instances"
      value       = module.ec2_private_app1.id
    }
    ## ec2_private_ip
    output "app1_ec2_private_ip" {
      description = "List of private IP addresses assigned to the instances"
      value       = module.ec2_private_app1.private_ip 
    }
    
    # App2 - Private EC2 Instances
    ## ec2_private_instance_ids
    output "app2_ec2_private_instance_ids" {
      description = "List of IDs of instances"
      value       = module.ec2_private_app2.id
    }
    ## ec2_private_ip
    output "app2_ec2_private_ip" {
      description = "List of private IP addresses assigned to the instances"
      value       = module.ec2_private_app2.private_ip 
    }
    

Step-08: c11-acm-certificatemanager.tf

  • Terraform AWS ACM Module
  • Create a SAN SSL Certificate using DNS Validation with Route53
  • This is required for us with ALB Load Balancer HTTPS Listener to associate SSL certificate to it
  • Test trimsuffic function using terraform console
    # Terraform Console
    terraform console
    
    # Provide Trim Suffix Function
    trimsuffix("devopsincloud.com.", ".")
    
    # Verify Output
    "devopsincloud.com"
    
  • ACM Module Terraform Configuration
    # ACM Module - To create and Verify SSL Certificates
    module "acm" {
      source  = "terraform-aws-modules/acm/aws"
      version = "~> 2.0"
    
      domain_name = trimsuffix(data.aws_route53_zone.mydomain.name, ".") 
      zone_id     = data.aws_route53_zone.mydomain.id
      subject_alternative_names = [
        "*.devopsincloud.com"
      ]
      tags = local.common_tags   
    }
    
    # Output ACM Certificate ARN
    output "acm_certificate_arn" {
      description = "ACM Certificate ARN"
      value = module.acm.this_acm_certificate_arn
    }
    

Step-09: c10-02-ALB-application-loadbalancer.tf

Step-09-01: HTTP to HTTPS Redirect

  # HTTP Listener - HTTP to HTTPS Redirect
    http_tcp_listeners = [
    {
      port               = 80
      protocol           = "HTTP"
      action_type = "redirect"
      redirect = {
        port        = "443"
        protocol    = "HTTPS"
        status_code = "HTTP_301"
      }
    }
  ]  

Step-09-02: Add Target Group app2

    # App2 Target Group - TG Index = 1
    {
      name_prefix          = "app2-"
      backend_protocol     = "HTTP"
      backend_port         = 80
      target_type          = "instance"
      deregistration_delay = 10
      health_check = {
        enabled             = true
        interval            = 30
        path                = "/app2/index.html"
        port                = "traffic-port"
        healthy_threshold   = 3
        unhealthy_threshold = 3
        timeout             = 6
        protocol            = "HTTP"
        matcher             = "200-399"
      }
      protocol_version = "HTTP1"
      # App2 Target Group - Targets
      targets = {
        my_app2_vm1 = {
          target_id = module.ec2_private_app2.id[0]
          port      = 80
        },
        my_app2_vm2 = {
          target_id = module.ec2_private_app2.id[1]
          port      = 80
        }
      }
      tags =local.common_tags # Target Group Tags
    }  

Step-09-03: Add HTTPS Listener

  1. Associate SSL Certificate ARN
  2. Add fixed response for Root Context /*
      # HTTPS Listener
      https_listeners = [
        # HTTPS Listener Index = 0 for HTTPS 443
        {
          port               = 443
          protocol           = "HTTPS"
          certificate_arn    = module.acm.this_acm_certificate_arn
          action_type = "fixed-response"
          fixed_response = {
            content_type = "text/plain"
            message_body = "Fixed Static message - for Root Context"
            status_code  = "200"
          }
        }, 
      ]
    

Step-09-04: Add HTTPS Listener Rules

  • Understand about https_listener_index
  • Create Rule-1: /app1* should go to App1 EC2 Instances
  • Understand about target_group_index
  • Create Rule-2: /app2* should go to App2 EC2 Instances
      # HTTPS Listener Rules
      https_listener_rules = [
        # Rule-1: /app1* should go to App1 EC2 Instances
        { 
          https_listener_index = 0
          actions = [
            {
              type               = "forward"
              target_group_index = 0
            }
          ]
          conditions = [{
            path_patterns = ["/app1*"]
          }]
        },
        # Rule-2: /app2* should go to App2 EC2 Instances    
        {
          https_listener_index = 0
          actions = [
            {
              type               = "forward"
              target_group_index = 1
            }
          ]
          conditions = [{
            path_patterns = ["/app2*"]
          }]
        },    
      ]
    

Step-10: c12-route53-dnsregistration.tf

  • Route53 Record Resource
    # DNS Registration 
    resource "aws_route53_record" "apps_dns" {
      zone_id = data.aws_route53_zone.mydomain.id
      name    = "apps9.devopsincloud.com"
      type    = "A"
    
      alias {
        name                   = module.alb.this_lb_dns_name
        zone_id                = module.alb.this_lb_zone_id
        evaluate_target_health = true
      }
    }
    

Step-11: Execute Terraform Commands

# Terraform Initialize
terraform init

# Terraform Validate
terraform validate

# Terraform Plan
terraform plan

# Terraform Apply
terraform apply -auto-approve

# Verify
Observation: 
1. Verify EC2 Instances for App1
2. Verify EC2 Instances for App2
3. Verify Load Balancer SG - Primarily SSL 443 Rule
4. Verify ALB Listener - HTTP:80 - Should contain a redirect from HTTP to HTTPS
5. Verify ALB Listener - HTTPS:443 - Should contain 3 rules 
5.1 /app1* to app1-tg 
5.2 /app2* to app2-tg 
5.3 /* return Fixed response
6. Verify ALB Target Groups App1 and App2, Targets (should be healthy) 
5. Verify SSL Certificate (Certificate Manager)
6. Verify Route53 DNS Record

# Test (Domain will be different for you based on your registered domain)
# Note: All the below URLS shoud redirect from HTTP to HTTPS
1. Fixed Response: http://apps.devopsincloud.com   
2. App1 Landing Page: http://apps.devopsincloud.com/app1/index.html
3. App1 Metadata Page: http://apps.devopsincloud.com/app1/metadata.html
4. App2 Landing Page: http://apps.devopsincloud.com/app2/index.html
5. App2 Metadata Page: http://apps.devopsincloud.com/app2/metadata.html

Step-12: Clean-Up

# Terraform Destroy
terraform destroy -auto-approve

# Delete files
rm -rf .terraform*
rm -rf terraform.tfstate*

References

🎉 New Course
Ultimate DevOps Real-World Project Implementation on AWS
$15.99 $84.99 81% OFF
MARCH2026
Enroll Now on Udemy →
🎉 Offer