Optimal ELB Health Check Configuration for Apache NameVirtualHosts with WWW Redirects


2 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>