Why does AWS ALB Health Checks Fail with Correct Security Group (EC2, Docker, nginx-proxy, ACM)?
I'm having trouble getting my AWS Application Load Balancer (ALB) health checks to pass when my EC2 instance's security group is configured correctly. The site works when I open port 443
to the world (0.0.0.0/0)
, but fails when I restrict it to the ALB's security group, even with Source/Destination Check disabled.
EC2 Instance Configuration:
- Docker Compose runs
nginx-proxy
,acme-companion
,Django (web)
, and other services. - nginx-proxy is mapped to ports
80
and443
on the host. - VIRTUAL_HOST is set to my domain.
- VIRTUAL_PORT is correctly set to
8000
- EC2 Instance Security Group:
- Correct Configuration (Failing): Allows inbound HTTPS (port 443) only from the ALB's security group (e.g., sg-xxxxxxxx).
- Temporary Workaround (Working): Allows inbound HTTPS (port 443) from 0.0.0.0/0.
- Source/Destination Check is disabled on the EC2 instance.
Request Flow:
Client Request -> Route 53 -> Application Load Balancer (HTTPS:443) -> AWS WAF -> ALB Target Group (HTTPS:443) -> EC2 Instance (port 443, nginx-proxy) -> Docker Container (port 8000, Django)
ALB Configuration:
- Listener on port 80 (HTTP) redirects to HTTPS (443).
- Listener on port 443 (HTTPS) forwards to the target group.
- ALB Security Group: Allows inbound on ports 80 and 443 from 0.0.0.0/0.
- Target Group health checks:
- Protocol: HTTPS
- Port: 443
- Path: /api/v1/health/ (I have this endpoint in my django application but this is what I get in my nginx-proxy logs
"/etc/nginx/html/api/v1/health/index.html" is not found (2: No such file or directory), client: 172.xx.x.xxx, server: , request: "GET /api/v1/health/ HTTP/1.1" host: "172.xx.x.xxx"
)
Why are the ALB health checks failing when the EC2 instance's security group correctly allows traffic only from the ALB's security group, even with Source/Destination Check disabled?
this worked for me: Try to forward the health check path to the root directory of your project then restart nginx inside your container