WHMCS Load Balancing Setup: Complete Guide to High-Availability & Auto-Scaling [2025]
Master WHMCS load balancing with HAProxy, Nginx, and enterprise clustering. Learn database replication, session management, and auto-scaling for 99.99% uptime hosting businesses.
16 min read Shahid Malla 2025-01-27
##
Infrastructure
Architecture Planning ### Multi-Server WHMCS Setup Before implementing
load balancing, design your infrastructure architecture: ```yaml # WHMCS
High-Availability Architecture # Infrastructure Requirements Planning
Load Balancer Tier: - Primary HAProxy/Nginx Server - Secondary
HAProxy/Nginx Server (Failover) - Virtual IP (VIP) Management - SSL
Certificate Management Application Tier: - WHMCS Server 1 (Primary) -
WHMCS Server 2 (Secondary) - WHMCS Server N (Auto-scaling) - Shared File
Storage (NFS/GlusterFS) Database Tier: - MySQL Master Server - MySQL
Slave Server(s) - Redis Cluster (Sessions) - Backup Systems Network
Requirements: - Minimum 1Gbps interconnect - VLAN isolation - Private
network for DB communication - Public network for client access ``` ###
Server Specifications Plan your server specifications based on expected
load: ```ini # Load Balancer Servers CPU: 4-8 cores RAM: 8-16GB Storage:
100GB SSD (logs, config) Network: 1Gbps+ dual NICs # WHMCS Application
Servers CPU: 8-16 cores RAM: 16-32GB Storage: 200GB SSD (application,
temp files) Network: 1Gbps+ dual NICs # Database Servers CPU: 16-32
cores RAM: 32-64GB Storage: 500GB-1TB NVMe SSD Network: 10Gbps (if
possible) # Shared Storage Type: NFS/GlusterFS/Ceph Capacity: 1TB+
(based on attachments, templates) Performance: High IOPS for file
operations ``` ##
Database Replication Setup ### MySQL Master-Slave Configuration Set
up database replication for high availability: ```bash #!/bin/bash #
MySQL Master-Slave Replication Setup Script # Master Server
Configuration setup_mysql_master() { echo "Configuring MySQL Master
Server..." # Edit MySQL configuration cat >>
/etc/mysql/mysql.conf.d/mysqld.cnf << 'EOF' # Master Server
Configuration [mysqld] # Replication Settings server-id = 1 log-bin =
mysql-bin binlog-format = ROW binlog-do-db = whmcs expire_logs_days = 7
max_binlog_size = 100M # Performance Optimization
innodb_buffer_pool_size = 2G innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2 innodb_flush_method = O_DIRECT #
Connection Settings max_connections = 1000 max_user_connections = 950
thread_cache_size = 100 # Security bind-address = 0.0.0.0 EOF # Restart
MySQL systemctl restart mysql # Create replication user mysql -u root -p
<< 'SQL' CREATE USER 'repl'@'%' IDENTIFIED BY
'SecureReplPassword123!'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES; SHOW MASTER STATUS; SQL } # Slave Server
Configuration setup_mysql_slave() { echo "Configuring MySQL Slave
Server..." # Edit MySQL configuration cat >>
/etc/mysql/mysql.conf.d/mysqld.cnf << 'EOF' # Slave Server
Configuration [mysqld] # Replication Settings server-id = 2 relay-log =
mysql-relay-log relay-log-index = mysql-relay-log.index read_only = 1 #
Performance Optimization innodb_buffer_pool_size = 2G
innodb_log_file_size = 256M innodb_flush_log_at_trx_commit = 2 #
Connection Settings max_connections = 1000 max_user_connections = 950
thread_cache_size = 100 # Security bind-address = 0.0.0.0 EOF # Restart
MySQL systemctl restart mysql # Configure slave replication read -p
"Enter Master server IP: " MASTER_IP read -p "Enter Master log file
(from SHOW MASTER STATUS): " LOG_FILE read -p "Enter Master log
position: " LOG_POSITION mysql -u root -p << SQL CHANGE MASTER TO
MASTER_HOST='${MASTER_IP}', MASTER_USER='repl',
MASTER_PASSWORD='SecureReplPassword123!',
MASTER_LOG_FILE='${LOG_FILE}',
MASTER_LOG_POS=${LOG_POSITION}; START SLAVE; SHOW SLAVE
STATUS\G SQL } # Execute based on server role echo "MySQL
Replication Setup" echo "1. Configure as Master" echo "2. Configure as
Slave" read -p "Select option: " OPTION case $OPTION in 1)
setup_mysql_master ;; 2) setup_mysql_slave ;; *) echo "Invalid option"
;; esac ``` ### Database Connection Management Configure WHMCS for
database load balancing: ```php <?php // WHMCS Database Load Balancer
Configuration // File: /var/www/whmcs/configuration_db.php class
WHMCSDBLoadBalancer { private $masterDB; private $slaveDB; private
$isReadQuery = false; // Database Configuration private $masterConfig =
[ 'host' => '10.0.1.10', // Master DB IP 'username' =>
'whmcs_user', 'password' => 'SecureDBPassword123!', 'database' =>
'whmcs', 'port' => 3306 ]; private $slaveConfig = [ 'host' =>
'10.0.1.11', // Slave DB IP 'username' => 'whmcs_user', 'password'
=> 'SecureDBPassword123!', 'database' => 'whmcs', 'port' =>
3306 ]; public function __construct() {
$this->connectDatabases(); } private function connectDatabases()
{ try { // Master connection (Read/Write) $this->masterDB =
new PDO(
"mysql:host={$this->masterConfig['host']};port={$this->masterConfig['port']};dbname={$this->masterConfig['database']}",
$this->masterConfig['username'], $this->masterConfig['password'],
[ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_INIT_COMMAND => "SET
NAMES utf8mb4 COLLATE utf8mb4_unicode_ci" ] ); // Slave connection (Read
Only) $this->slaveDB = new PDO(
"mysql:host={$this->slaveConfig['host']};port={$this->slaveConfig['port']};dbname={$this->slaveConfig['database']}",
$this->slaveConfig['username'], $this->slaveConfig['password'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_INIT_COMMAND => "SET
NAMES utf8mb4 COLLATE utf8mb4_unicode_ci" ] ); } catch
(PDOException $e) { error_log("Database connection failed: " .
$e->getMessage()); throw new Exception("Database connection error");
} } public function query($sql, $params = []) {
$this->isReadQuery = $this->isSelectQuery($sql); // Use slave for
read operations, master for write operations $db = $this->isReadQuery
? $this->slaveDB : $this->masterDB; // Fallback to master if slave
is unavailable if ($this->isReadQuery && !$this->isSlaveHealthy())
{ $db = $this->masterDB; error_log("Slave DB unhealthy, using
master for read query"); } try { $stmt =
$db->prepare($sql); $stmt->execute($params); return
$this->isReadQuery ? $stmt->fetchAll() : $stmt->rowCount();
} catch (PDOException $e) { error_log("Query failed: " .
$e->getMessage()); // Retry on master if slave query fails if
($this->isReadQuery && $db === $this->slaveDB) { $stmt =
$this->masterDB->prepare($sql); $stmt->execute($params); return
$stmt->fetchAll(); } throw $e; } } private function
isSelectQuery($sql) { $sql = trim($sql); return stripos($sql,
'SELECT') === 0 || stripos($sql, 'SHOW') === 0 || stripos($sql,
'DESCRIBE') === 0 || stripos($sql, 'EXPLAIN') === 0; } private
function isSlaveHealthy() { try { $stmt =
$this->slaveDB->query("SHOW SLAVE STATUS"); $status =
$stmt->fetch(); return $status && $status['Slave_IO_Running'] ===
'Yes' && $status['Slave_SQL_Running'] === 'Yes' &&
$status['Seconds_Behind_Master'] < 30; // Less than 30 seconds lag
} catch (PDOException $e) { return false; } } public
function beginTransaction() { return
$this->masterDB->beginTransaction(); } public function
commit() { return $this->masterDB->commit(); } public
function rollback() { return $this->masterDB->rollback();
} } // Initialize database load balancer $dbLoadBalancer = new
WHMCSDBLoadBalancer(); // Override WHMCS database functions function
Capsule() { global $dbLoadBalancer; return $dbLoadBalancer; }
?> ``` ##
HAProxy Load Balancer Configuration ### Primary HAProxy Setup
Configure HAProxy for WHMCS load balancing: ```bash #!/bin/bash #
HAProxy Installation and Configuration for WHMCS install_haproxy()
{ echo "Installing HAProxy..." apt update apt install haproxy -y #
Enable HAProxy systemctl enable haproxy } configure_haproxy()
{ echo "Configuring HAProxy for WHMCS..." # Backup original
configuration cp /etc/haproxy/haproxy.cfg
/etc/haproxy/haproxy.cfg.backup # Create HAProxy configuration cat >
/etc/haproxy/haproxy.cfg << 'EOF' # HAProxy Configuration for
WHMCS Load Balancing global log stdout local0 chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin stats timeout
30s user haproxy group haproxy daemon # SSL Configuration
ssl-default-bind-ciphers
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets #
Performance Tuning tune.ssl.default-dh-param 2048 tune.bufsize 32768
tune.maxrewrite 8192 defaults mode http log global option httplog option
dontlognull option log-health-checks option forwardfor option
http-server-close # Timeouts timeout connect 5000ms timeout client
50000ms timeout server 50000ms timeout http-request 10s timeout
http-keep-alive 10s timeout check 5s # Error handling errorfile 400
/etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http errorfile 500
/etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http errorfile 504
/etc/haproxy/errors/504.http # Frontend Configuration frontend
whmcs_frontend bind *:80 bind *:443 ssl crt /etc/ssl/certs/whmcs.pem #
Redirect HTTP to HTTPS redirect scheme https code 301 if !{ ssl_fc
} # Security Headers http-response set-header
Strict-Transport-Security "max-age=31536000; includeSubDomains"
http-response set-header X-Frame-Options "SAMEORIGIN" http-response
set-header X-Content-Type-Options "nosniff" http-response set-header
X-XSS-Protection "1; mode=block" # Rate Limiting stick-table type ip
size 100k expire 30s store http_req_rate(10s) http-request track-sc0 src
http-request deny if { sc_http_req_rate(0) gt 50 } # Load
Balancing Rules use_backend whmcs_admin if { path_beg /admin }
use_backend whmcs_api if { path_beg /includes/api.php }
default_backend whmcs_web # Backend Configurations # Web Backend (Client
Area) backend whmcs_web balance roundrobin option httpchk GET /ping.php
HTTP/1.1\r\nHost:\ whmcs.yourdomain.com # Session Persistence (IP Hash)
hash-type consistent balance source # Server Definitions server whmcs1
10.0.1.20:80 check inter 5s rise 2 fall 3 weight 100 server whmcs2
10.0.1.21:80 check inter 5s rise 2 fall 3 weight 100 # Backup server
server whmcs_backup 10.0.1.22:80 check inter 10s rise 2 fall 5 backup #
Admin Backend (Admin Area) backend whmcs_admin balance leastconn option
httpchk GET /admin/ping.php HTTP/1.1\r\nHost:\ whmcs.yourdomain.com #
Sticky sessions for admin area cookie SERVERID insert indirect nocache
server whmcs1 10.0.1.20:80 check cookie s1 inter 5s rise 2 fall 3 server
whmcs2 10.0.1.21:80 check cookie s2 inter 5s rise 2 fall 3 # API Backend
backend whmcs_api balance leastconn option httpchk GET /api_health.php
HTTP/1.1\r\nHost:\ whmcs.yourdomain.com # API Rate limiting stick-table
type ip size 10k expire 1m store http_req_rate(1m) http-request
track-sc1 src http-request deny if { sc_http_req_rate(1) gt 100
} server whmcs1 10.0.1.20:80 check inter 3s rise 2 fall 3 server
whmcs2 10.0.1.21:80 check inter 3s rise 2 fall 3 # Statistics Interface
listen stats bind *:8404 stats enable stats uri /stats stats refresh 30s
stats admin if TRUE # Basic Authentication stats auth
admin:SecureStatsPassword123! # Show detailed server information stats
show-legends stats show-desc WHMCS Load Balancer Statistics EOF # Create
health check scripts create_health_checks # Test configuration haproxy
-c -f /etc/haproxy/haproxy.cfg if [ $? -eq 0 ]; then echo "HAProxy
configuration is valid" systemctl restart haproxy systemctl status
haproxy else echo "HAProxy configuration has errors" exit 1 fi }
create_health_checks() { echo "Creating health check scripts..." #
Create ping script for each WHMCS server for server in whmcs1 whmcs2; do
ssh
[email protected] "cat > /var/www/whmcs/ping.php << 'PHP'
<?php // HAProxy Health Check Script header('Content-Type:
text/plain'); // Check database connection try { \$pdo = new
PDO('mysql:host=10.0.1.10;dbname=whmcs', 'whmcs_user', 'password');
\$stmt = \$pdo->query('SELECT 1'); \$dbStatus = 'OK'; } catch
(Exception \$e) { \$dbStatus = 'FAIL'; http_response_code(503);
} // Check file system \$filesystemStatus = is_writable('/tmp') ?
'OK' : 'FAIL'; if (\$filesystemStatus === 'FAIL') {
http_response_code(503); } // Check Redis try { \$redis = new
Redis(); \$redis->connect('127.0.0.1', 6379); \$redis->ping();
\$redisStatus = 'OK'; \$redis->close(); } catch (Exception \$e)
{ \$redisStatus = 'FAIL'; } // Response if (\$dbStatus ===
'OK' && \$filesystemStatus === 'OK') { echo \"WHMCS_OK\nDB:
\$dbStatus\nFS: \$filesystemStatus\nRedis: \$redisStatus\nTime: \" .
date('Y-m-d H:i:s'); } else { http_response_code(503); echo
\"WHMCS_FAIL\nDB: \$dbStatus\nFS: \$filesystemStatus\nRedis:
\$redisStatus\nTime: \" . date('Y-m-d H:i:s'); } ?> PHP" done
} install_haproxy configure_haproxy echo "HAProxy installation and
configuration completed!" echo "Access statistics at:
http://your-lb-ip:8404/stats" echo "Username: admin" echo "Password:
SecureStatsPassword123!" ``` ##
Session Management & File
Synchronization ### Redis Session Clustering Set up Redis for shared
sessions across WHMCS servers: ```bash #!/bin/bash # Redis Cluster Setup
for WHMCS Sessions setup_redis_cluster() { echo "Setting up Redis
Cluster for WHMCS sessions..." # Install Redis on all WHMCS servers for
server in 10.0.1.20 10.0.1.21 10.0.1.22; do ssh root@$server " apt
update apt install redis-server -y # Configure Redis for clustering cat
> /etc/redis/redis.conf << 'REDIS_CONF' # Redis Configuration
for WHMCS Session Clustering bind 0.0.0.0 port 6379 protected-mode yes
requireauth SecureRedisPassword123! # Memory Configuration maxmemory 1gb
maxmemory-policy allkeys-lru maxmemory-samples 5 # Persistence (for
sessions) save 900 1 save 300 10 save 60 10000 # Performance databases
16 tcp-keepalive 300 timeout 0 tcp-backlog 511 # Session-specific
settings notify-keyspace-events Ex REDIS_CONF systemctl restart
redis-server systemctl enable redis-server " done echo "Redis cluster
setup completed!" } configure_php_sessions() { echo
"Configuring PHP sessions for Redis..." for server in 10.0.1.20
10.0.1.21 10.0.1.22; do ssh root@$server " # Configure PHP to use Redis
for sessions cat >> /etc/php/8.1/fpm/conf.d/99-redis-sessions.ini
<< 'PHP_CONF' ; Redis Session Configuration session.save_handler =
redis session.save_path =
\"tcp://10.0.1.20:6379?auth=SecureRedisPassword123!,tcp://10.0.1.21:6379?auth=SecureRedisPassword123!,tcp://10.0.1.22:6379?auth=SecureRedisPassword123!\"
session.gc_maxlifetime = 7200 session.gc_probability = 1
session.gc_divisor = 100 PHP_CONF systemctl restart php8.1-fpm " done
} setup_redis_cluster configure_php_sessions ``` ### File System
Synchronization Set up shared storage for WHMCS files: ```bash
#!/bin/bash # NFS Shared Storage Setup for WHMCS setup_nfs_server()
{ echo "Setting up NFS server for shared WHMCS storage..." #
Install NFS server (on dedicated storage server) apt update apt install
nfs-kernel-server -y # Create shared directories mkdir -p
/shared/whmcs/{attachments,downloads,uploads,templates_c}
chown -R www-data:www-data /shared/whmcs chmod -R 755 /shared/whmcs #
Configure NFS exports cat >> /etc/exports << 'NFS_EXPORTS' #
WHMCS Shared Storage Exports /shared/whmcs/attachments
10.0.1.0/24(rw,sync,no_subtree_check,no_root_squash)
/shared/whmcs/downloads
10.0.1.0/24(rw,sync,no_subtree_check,no_root_squash)
/shared/whmcs/uploads
10.0.1.0/24(rw,sync,no_subtree_check,no_root_squash)
/shared/whmcs/templates_c
10.0.1.0/24(rw,sync,no_subtree_check,no_root_squash) NFS_EXPORTS # Apply
exports exportfs -ra systemctl restart nfs-kernel-server systemctl
enable nfs-kernel-server echo "NFS server setup completed!" }
configure_nfs_clients() { echo "Configuring NFS clients on WHMCS
servers..." for server in 10.0.1.20 10.0.1.21 10.0.1.22; do ssh
root@$server " # Install NFS client apt update apt install nfs-common -y
# Create mount points mkdir -p
/var/www/whmcs/{attachments,downloads,uploads,templates_c} #
Configure auto-mounting cat >> /etc/fstab << 'FSTAB' # WHMCS
NFS Mounts 10.0.1.30:/shared/whmcs/attachments
/var/www/whmcs/attachments nfs
defaults,_netdev,rsize=32768,wsize=32768,timeo=14,intr 0 0
10.0.1.30:/shared/whmcs/downloads /var/www/whmcs/downloads nfs
defaults,_netdev,rsize=32768,wsize=32768,timeo=14,intr 0 0
10.0.1.30:/shared/whmcs/uploads /var/www/whmcs/uploads nfs
defaults,_netdev,rsize=32768,wsize=32768,timeo=14,intr 0 0
10.0.1.30:/shared/whmcs/templates_c /var/www/whmcs/templates_c nfs
defaults,_netdev,rsize=32768,wsize=32768,timeo=14,intr 0 0 FSTAB # Mount
all NFS shares mount -a # Set proper permissions chown -R
www-data:www-data
/var/www/whmcs/{attachments,downloads,uploads,templates_c} "
done } # Execute setup echo "NFS Shared Storage Setup" echo "1.
Setup NFS Server" echo "2. Configure NFS Clients" echo "3. Both" read -p
"Select option: " OPTION case $OPTION in 1) setup_nfs_server ;; 2)
configure_nfs_clients ;; 3) setup_nfs_server && configure_nfs_clients ;;
*) echo "Invalid option" ;; esac ``` ##
Monitoring & Health
Checks ### Comprehensive Monitoring Setup Monitor your load-balanced
WHMCS environment: ```bash #!/bin/bash # WHMCS Load Balancer Monitoring
Setup install_monitoring_tools() { echo "Installing monitoring
tools..." # Install Prometheus and Grafana apt update apt install -y
prometheus grafana-server # Enable services systemctl enable prometheus
systemctl enable grafana-server systemctl start prometheus systemctl
start grafana-server } configure_haproxy_monitoring() { echo
"Configuring HAProxy monitoring..." # Add HAProxy stats to Prometheus
cat >> /etc/prometheus/prometheus.yml << 'PROMETHEUS' -
job_name: 'haproxy' static_configs: - targets: ['localhost:8404']
metrics_path: /stats params: csv: [''] PROMETHEUS # Install HAProxy
exporter wget
https://github.com/prometheus/haproxy_exporter/releases/download/v0.13.0/haproxy_exporter-0.13.0.linux-amd64.tar.gz
tar xzf haproxy_exporter-0.13.0.linux-amd64.tar.gz mv
haproxy_exporter-0.13.0.linux-amd64/haproxy_exporter /usr/local/bin/ #
Create systemd service cat >
/etc/systemd/system/haproxy-exporter.service << 'SERVICE' [Unit]
Description=HAProxy Exporter After=network.target [Service] Type=simple
User=prometheus ExecStart=/usr/local/bin/haproxy_exporter
--haproxy.scrape-uri="http://admin:SecureStatsPassword123!@localhost:8404/stats?stats;csv"
Restart=always [Install] WantedBy=multi-user.target SERVICE systemctl
daemon-reload systemctl enable haproxy-exporter systemctl start
haproxy-exporter } create_monitoring_dashboard() { echo
"Creating monitoring dashboard..." # Create custom WHMCS monitoring
script cat > /usr/local/bin/whmcs-monitor.py << 'PYTHON'
#!/usr/bin/env python3 # WHMCS Load Balancer Monitoring Script import
requests import json import time import subprocess from datetime import
datetime class WHMCSMonitor: def __init__(self): self.servers = [
{'name': 'whmcs1', 'url': 'http://10.0.1.20/ping.php'},
{'name': 'whmcs2', 'url': 'http://10.0.1.21/ping.php'},
{'name': 'whmcs_backup', 'url': 'http://10.0.1.22/ping.php'} ]
self.load_balancer_url = 'http://localhost:8404/stats' self.metrics_file
= '/var/log/whmcs-metrics.log' def check_server_health(self, server):
try: start_time = time.time() response = requests.get(server['url'],
timeout=5) response_time = time.time() - start_time return {
'name': server['name'], 'status': 'healthy' if response.status_code ==
200 else 'unhealthy', 'response_time': response_time, 'status_code':
response.status_code, 'timestamp': datetime.now().isoformat() }
except Exception as e: return { 'name': server['name'], 'status':
'unhealthy', 'response_time': None, 'error': str(e), 'timestamp':
datetime.now().isoformat() } def get_haproxy_stats(self): try:
response = requests.get( self.load_balancer_url, auth=('admin',
'SecureStatsPassword123!'), timeout=5 ) if response.status_code == 200:
# Parse HAProxy stats lines = response.text.strip().split('\n') stats =
[] for line in lines: if line.startswith('#') or not line.strip():
continue fields = line.split(',') if len(fields) >= 33: # HAProxy
stats format stats.append({ 'proxy_name': fields[0], 'server_name':
fields[1], 'current_sessions': fields[4], 'max_sessions': fields[5],
'total_sessions': fields[7], 'status': fields[17], 'weight': fields[18],
'check_status': fields[36] if len(fields) > 36 else 'N/A' })
return stats except Exception as e: return {'error': str(e)}
def monitor_loop(self): while True: print(f"[{datetime.now()}]
Starting monitoring cycle...") # Check server health server_metrics = []
for server in self.servers: metrics = self.check_server_health(server)
server_metrics.append(metrics) print(f" {metrics['name']}:
{metrics['status']} ({metrics.get('response_time',
'N/A')}s)") # Get HAProxy stats haproxy_stats =
self.get_haproxy_stats() # Log metrics with open(self.metrics_file, 'a')
as f: f.write(json.dumps({ 'timestamp': datetime.now().isoformat(),
'servers': server_metrics, 'haproxy': haproxy_stats }) + '\n') #
Check for alerts self.check_alerts(server_metrics) time.sleep(60) #
Monitor every minute def check_alerts(self, server_metrics):
unhealthy_servers = [s for s in server_metrics if s['status'] ==
'unhealthy'] if unhealthy_servers: alert_message = f"ALERT:
{len(unhealthy_servers)} server(s) unhealthy: " alert_message
+= ", ".join([s['name'] for s in unhealthy_servers])
print(alert_message) # Send alert (customize based on your notification
system) subprocess.run(['logger', '-t', 'whmcs-monitor', alert_message])
if __name__ == "__main__": monitor = WHMCSMonitor()
monitor.monitor_loop() PYTHON chmod +x /usr/local/bin/whmcs-monitor.py #
Create systemd service for monitoring cat >
/etc/systemd/system/whmcs-monitor.service << 'SERVICE' [Unit]
Description=WHMCS Load Balancer Monitor After=network.target [Service]
Type=simple User=prometheus ExecStart=/usr/local/bin/whmcs-monitor.py
Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
SERVICE systemctl daemon-reload systemctl enable whmcs-monitor systemctl
start whmcs-monitor } install_monitoring_tools
configure_haproxy_monitoring create_monitoring_dashboard echo
"Monitoring setup completed!" echo "Grafana dashboard:
http://your-server:3000" echo "Default credentials: admin/admin" echo
"HAProxy stats: http://your-server:8404/stats" ```