Configuring HTTPS Connections between ALB and NGINX Backend Using Self-Signed SSL Certificate

I’m looking for guidance on setting up HTTPS communication from my AWS Application Load Balancer (ALB) to my backend NGINX servers hosted on EC2. I’ve successfully set up SSL termination for incoming connections at the ALB, but I now want to ensure that my traffic to the NGINX instances is also encrypted using a self-signed certificate.

Despite following AWS guidelines, I encounter 502 Bad Gateway errors when accessing the service, and I’m unsure where the issue lies. Here’s what I have checked so far:

  • The security groups are set to allow traffic on port 443 between the ALB and the EC2 instances.
  • VPC settings are configured properly since HTTP requests on port 80 are functioning fine.
  • NGINX is set up to listen on port 443 for HTTPS and responds correctly when accessed directly.
  • I have created a public key policy with my self-signed certificate.
  • The backend authentication policy is properly established.
  • Ensured the SSL negotiation policy is compatible with what I’ve configured in NGINX.
  • My NGINX log files only show HTTP requests and not any HTTPS traffic.

What steps can I take to diagnose or troubleshoot this further? Are there other debugging techniques you would recommend?

Here’s the current configuration I have for my ALB:

aws elbv2 describe-load-balancers --names my-load-balancer
{
  "LoadBalancers": [{
    "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-west-2:123456789:loadbalancer/app/my-load-balancer/abc",
    "DNSName": "my-load-balancer-123456.us-west-2.elb.amazonaws.com",
    "Type": "application",
    "Scheme": "internet-facing",
    "VpcId": "vpc-xyz987",
    "State": {"Code": "active"},
    "AvailabilityZones": [
      {"ZoneName": "us-west-2a", "SubnetId": "subnet-xyz"},
      {"ZoneName": "us-west-2b", "SubnetId": "subnet-abc"}
    ],
    "SecurityGroups": ["sg-xyz987"]
  }]
}

And here’s my NGINX virtual host setup:

server {
    listen 443 ssl;
    server_name mydomain.com;
    root /var/www/html;

    ssl_certificate /path/to/my.crt;
    ssl_certificate_key /path/to/my.key;

    ssl_protocols TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

The following are the commands I ran to generate the necessary SSL certificate:

openssl genrsa -out /path/to/my.key 2048
openssl req -new -key /path/to/my.key -out /path/to/my.csr
openssl x509 -req -days 365 -in /path/to/my.csr -signkey /path/to/my.key -out /path/to/my.crt

check your target group settings - sounds like alb might still be routing to port 80 instead of 443. also verify the health check is configured for https with the right path, otherwise instances will show unhealthy. had same issue last month and it was just the target group protocol setting.

hmm interesting setup! are you seeing anything in the alb access logs about ssl handshake failures? also curious - when you say nginx logs only show http requests, are you checking the error logs too or just access logs? might be worth enabling debug logging temporarly to see whats happening during the ssl negotiation.

The configuration appears mostly correct, but there’s a critical mismatch in your NGINX SSL certificate setup. When ALB connects to your backend, it needs to validate the certificate’s Common Name or Subject Alternative Name against the actual hostname it’s connecting to. Since ALB connects directly to your EC2 instance’s private IP or hostname, your self-signed certificate should match that identifier rather than ‘mydomain.com’. Try regenerating your certificate with the EC2 instance’s private DNS name or IP address as the Common Name. Additionally, verify your target group’s health check is using HTTPS protocol and the correct path. I encountered similar issues when the certificate hostname didn’t align with how ALB was addressing the backend servers.