Optimal ELB Health Check Configuration for Apache NameVirtualHosts with WWW Redirects


12 views

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:

  1. Go to EC2 Console → Load Balancers
  2. Select your ELB → Health Check tab
  3. Change "Ping Protocol" to TCP
  4. 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>