When running Apache with NameVirtualHosts and automatic www redirection, ELB health checks can fail because they interpret HTTP 302 redirects as unhealthy instances. This occurs because:
# Typical health check settings that fail
HealthCheckProtocol: HTTP
HealthCheckPath: /
HealthCheckPort: 80
Your current vhost configuration creates a redirect loop for health checks:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias *.example.com
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ http://www.example.com/$1 [R=301,L]
</VirtualHost>
Option 1: TCP Health Check (Recommended for Stability)
Simplest solution that bypasses HTTP protocol issues:
HealthCheckProtocol: TCP
HealthCheckPort: 80
Option 2: Custom HTTP Endpoint
Add a dedicated health check path that bypasses redirects:
<VirtualHost *:80>
ServerName healthcheck.example.com
<Location "/health">
RewriteEngine Off
</Location>
</VirtualHost>
Option 3: Conditional Rewrite Rules
Modify your existing configuration to exempt health checks:
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ http://www.example.com/$1 [R=301,L]
- Use TCP checks for basic connectivity verification
- Combine with CloudWatch metrics for deeper monitoring
- Set appropriate timeout thresholds (5-10 seconds)
- Configure healthy/unhealthy threshold counts (2/3 works well)
For environments requiring HTTP checks with redirects:
<VirtualHost *:80>
ServerName internal-health.example.com
DocumentRoot /var/www/health
<Directory "/var/www/health">
Options -Indexes
AllowOverride None
Require all granted
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^ELB-HealthChecker
RewriteRule ^ - [L]
</Directory>
</VirtualHost>
When you're running Apache with NameVirtualHosts and implementing www redirects through mod_rewrite, Amazon's Elastic Load Balancer (ELB) health checks can become problematic. The default HTTP health check expects a 200 OK response, but your configuration likely returns a 302 redirect instead.
# Current problematic configuration
ServerName www.example.com
ServerAlias *.example.com
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ http://www.example.com/$1 [R=301,L]
ELB health checks work by sending HTTP requests to your instances. By default, it:
- Sends requests to the root path (/)
- Expects HTTP 200 response
- Follows redirects but doesn't count them as healthy
- Can be configured with custom paths and expected response codes
Here are three ways to solve this issue, ranked by preference:
1. Create a Dedicated Health Check Endpoint
The cleanest solution is to create a specific endpoint just for health checks:
<VirtualHost *:80>
ServerName health.example.com
DocumentRoot /var/www/health
<Location /health-check>
RewriteEngine Off
</Location>
</VirtualHost>
Then configure ELB to check health.example.com/health-check
2. Modify Your Rewrite Rules to Exclude Health Checks
Add an exception for the ELB's User-Agent:
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ http://www.example.com/$1 [R=301,L]
3. Switch to TCP Health Checks
As a last resort, you can use TCP health checks instead of HTTP:
- Go to EC2 Console → Load Balancers
- Select your ELB → Health Check tab
- Change "Ping Protocol" to TCP
- Set "Ping Port" to 80 or 443
For mission-critical applications, consider these additional measures:
- Implement both HTTP and TCP health checks
- Set appropriate timeout and interval values (e.g., 5-second interval, 2-second timeout)
- Configure healthy/unhealthy thresholds (e.g., 2 healthy to mark as InService, 3 failed to mark as OutOfService)
- Monitor health check metrics in CloudWatch
Here's a production-ready virtual host configuration that handles both regular traffic and health checks:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias *.example.com
# Health check direct access
<Location /health>
RewriteEngine Off
Header set Content-Type text/plain
ErrorDocument 200 "OK"
return 200
</Location>
# Regular traffic rules
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} !^ELB-HealthChecker
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ http://www.example.com/$1 [R=301,L]
# Your regular configuration continues...
</VirtualHost>