Implement Apache load balancing with SSL termination and health checks

Advanced 45 min Jun 09, 2026 17 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Configure Apache HTTP Server 2.4 with mod_proxy_balancer for high availability load balancing, SSL termination using Let's Encrypt certificates, and automated backend health monitoring with mod_proxy_hcheck for production environments.

Prerequisites

  • Root access to server
  • Domain name pointing to server
  • Multiple backend servers running web applications
  • Basic Apache administration knowledge

What this solves

Apache load balancing with SSL termination centralizes certificate management while distributing traffic across multiple backend servers. This setup provides high availability, automatic failover, and simplified SSL certificate handling for web applications that need to scale beyond a single server.

Step-by-step configuration

Update system packages

Start by updating your package manager to ensure you get the latest Apache version with security patches.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install Apache and required modules

Install Apache HTTP Server along with the proxy and SSL modules needed for load balancing and SSL termination.

sudo apt install -y apache2 certbot python3-certbot-apache
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
sudo a2enmod ssl
sudo a2enmod headers
sudo a2enmod proxy_hcheck
sudo dnf install -y httpd mod_ssl certbot python3-certbot-apache
sudo systemctl enable --now httpd

Configure the load balancer virtual host

Create a virtual host configuration that defines your backend servers and load balancing rules. This example uses two backend servers with health checks.


    ServerName example.com
    ServerAlias www.example.com
    
    # Redirect all HTTP traffic to HTTPS
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]



    ServerName example.com
    ServerAlias www.example.com
    
    # SSL Configuration (certificates will be added by certbot)
    SSLEngine on
    
    # Security headers
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    
    # Define backend servers with health checks
    ProxyPreserveHost On
    ProxyRequests Off
    
    # Health check configuration
    ProxyHCMethod GET
    ProxyHCUri /health
    ProxyHCInterval 10
    
    # Define the balancer cluster
    ProxyPass /balancer-manager !
    ProxyPass / balancer://mycluster/
    ProxyPassReverse / balancer://mycluster/
    
    # Backend server definitions
    
        # Backend server 1
        BalancerMember http://203.0.113.10:8080 route=app1 hcmethod=GET hcuri=/health
        # Backend server 2
        BalancerMember http://203.0.113.11:8080 route=app2 hcmethod=GET hcuri=/health
        
        # Load balancing method
        ProxySet lbmethod=byrequests
        
        # Health check settings
        ProxySet hcmethod=GET
        ProxySet hcuri=/health
        ProxySet hcinterval=10
        ProxySet retry=5
    
    
    # Balancer manager (restrict access in production)
    
        SetHandler balancer-manager
        Require ip 127.0.0.1
        Require ip 203.0.113.0/24
    
    
    # Logging
    ErrorLog ${APACHE_LOG_DIR}/loadbalancer_error.log
    CustomLog ${APACHE_LOG_DIR}/loadbalancer_access.log combined

    ServerName example.com
    ServerAlias www.example.com
    
    # Redirect all HTTP traffic to HTTPS
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]



    ServerName example.com
    ServerAlias www.example.com
    
    # SSL Configuration (certificates will be added by certbot)
    SSLEngine on
    
    # Security headers
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    
    # Define backend servers with health checks
    ProxyPreserveHost On
    ProxyRequests Off
    
    # Health check configuration
    ProxyHCMethod GET
    ProxyHCUri /health
    ProxyHCInterval 10
    
    # Define the balancer cluster
    ProxyPass /balancer-manager !
    ProxyPass / balancer://mycluster/
    ProxyPassReverse / balancer://mycluster/
    
    # Backend server definitions
    
        # Backend server 1
        BalancerMember http://203.0.113.10:8080 route=app1 hcmethod=GET hcuri=/health
        # Backend server 2
        BalancerMember http://203.0.113.11:8080 route=app2 hcmethod=GET hcuri=/health
        
        # Load balancing method
        ProxySet lbmethod=byrequests
        
        # Health check settings
        ProxySet hcmethod=GET
        ProxySet hcuri=/health
        ProxySet hcinterval=10
        ProxySet retry=5
    
    
    # Balancer manager (restrict access in production)
    
        SetHandler balancer-manager
        Require ip 127.0.0.1
        Require ip 203.0.113.0/24
    
    
    # Logging
    ErrorLog /var/log/httpd/loadbalancer_error.log
    CustomLog /var/log/httpd/loadbalancer_access.log combined

Enable required Apache modules and site

Enable the necessary Apache modules and activate your load balancer configuration.

sudo a2enmod rewrite
sudo a2ensite loadbalancer.conf
sudo a2dissite 000-default.conf
sudo systemctl enable --now apache2
# Modules are loaded automatically on RHEL-based systems
sudo systemctl restart httpd

Configure firewall rules

Open the necessary ports for HTTP, HTTPS, and the balancer manager interface.

sudo ufw allow 'Apache Full'
sudo ufw enable
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Obtain SSL certificates

Use Certbot to automatically obtain and configure SSL certificates from Let's Encrypt.

sudo certbot --apache -d example.com -d www.example.com
Note: Make sure your domain points to your load balancer's IP address before running certbot. The certificate validation requires your domain to be accessible.

Configure advanced load balancing options

Create additional configuration for session stickiness and advanced failover behavior.

# Advanced load balancer settings

Enable mod_proxy_express for better performance

LoadModule proxy_express_module modules/mod_proxy_express.so

Connection pooling settings

ProxyTimeout 30 ProxyBadHeader Ignore

For session stickiness (if your app requires it)

Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/; HttpOnly; Secure"

Health check configuration

# Global health check settings ProxyHCTPsize 16

Status monitoring

SetHandler server-status Require ip 127.0.0.1 Require ip 203.0.113.0/24 SetHandler server-info Require ip 127.0.0.1 Require ip 203.0.113.0/24
# Advanced load balancer settings

Connection pooling settings

ProxyTimeout 30 ProxyBadHeader Ignore

For session stickiness (if your app requires it)

Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/; HttpOnly; Secure"

Health check configuration

# Global health check settings ProxyHCTPsize 16

Status monitoring

SetHandler server-status Require ip 127.0.0.1 Require ip 203.0.113.0/24 SetHandler server-info Require ip 127.0.0.1 Require ip 203.0.113.0/24

Enable advanced configuration

Activate the advanced balancer settings and restart Apache to apply all changes.

sudo a2enconf balancer-advanced
sudo systemctl restart apache2
sudo systemctl restart httpd

Set up certificate auto-renewal

Configure automatic renewal of Let's Encrypt certificates to prevent expiration.

sudo systemctl enable --now certbot.timer
sudo systemctl list-timers certbot

Configure backend server health endpoints

Create health check endpoints

Your backend servers need to respond to health check requests. Here's an example for different server types.

// Simple health check endpoint
app.get('/health', (req, res) => {
    res.status(200).json({
        status: 'healthy',
        timestamp: new Date().toISOString(),
        uptime: process.uptime()
    });
});
@app.route('/health')
def health_check():
    return {
        'status': 'healthy',
        'timestamp': datetime.now().isoformat()
    }, 200

Verify your setup

Test Apache configuration

Verify the Apache configuration syntax and check service status.

sudo apache2ctl configtest
sudo systemctl status apache2
sudo httpd -t
sudo systemctl status httpd

Check SSL certificate status

Verify SSL certificates are properly installed and configured.

sudo certbot certificates
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

Test load balancing

Access the balancer manager interface and verify backend server status.

curl -I https://example.com/balancer-manager
curl -k https://example.com/
curl -k https://example.com/ | grep -i server

Verify health checks

Check that health checks are working and backend servers are being monitored.

sudo tail -f /var/log/apache2/loadbalancer_access.log
sudo grep "health check" /var/log/apache2/error.log
sudo tail -f /var/log/httpd/loadbalancer_access.log
sudo grep "health check" /var/log/httpd/error_log

Common issues

Symptom Cause Fix
502 Bad Gateway errors Backend servers unreachable Check backend server status and firewall rules. Verify ProxyPass URLs are correct
Health checks failing Backend health endpoint missing Implement /health endpoint on backend servers or change hcuri setting
SSL certificate errors Domain not pointing to load balancer Update DNS records to point to load balancer IP before running certbot
Session stickiness not working Backend servers not setting route cookies Enable cookie-based routing or use IP-based stickiness with Header add Set-Cookie
Balancer manager access denied IP restrictions too strict Update Require ip directives to include your management network
Performance issues Default connection limits Tune ProxyTimeout, KeepAlive settings and backend connection pools

Advanced load balancing strategies

Configure weighted round-robin

Assign different weights to backend servers based on their capacity.


    # High-capacity server gets more traffic
    BalancerMember http://203.0.113.10:8080 route=app1 loadfactor=3
    # Standard capacity server
    BalancerMember http://203.0.113.11:8080 route=app2 loadfactor=1
    # Backup server (only used when others fail)
    BalancerMember http://203.0.113.12:8080 route=app3 status=+H loadfactor=1
    
    ProxySet lbmethod=byrequests

Configure response time-based balancing

Use response time to determine the best backend server for new requests.

# Enable mod_proxy_express for response time tracking
a2enmod proxy_express


    BalancerMember http://203.0.113.10:8080 route=app1
    BalancerMember http://203.0.113.11:8080 route=app2
    
    # Use response time-based load balancing
    ProxySet lbmethod=heartbeat
    # Fallback to requests if heartbeat unavailable
    ProxySet lbmethod=byrequests

Monitoring and maintenance

Monitor your Apache load balancer with tools like Apache log analysis with GoAccess and ELK stack for real-time traffic insights. Set up Prometheus alerting with AlertManager to monitor backend server health and response times.

Regular maintenance includes monitoring certificate expiration, reviewing load balancing metrics through the balancer-manager interface, and analyzing access logs for traffic patterns and performance optimization opportunities.

Next steps

Running this in production?

Want this handled for you? Running this at scale adds a second layer of work: capacity planning, failover drills, cost control, and on-call. Our managed platform covers monitoring, backups and 24/7 response by default.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed cloud infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.