Files
Linux-Server-Management-Too…/modules/performance/nginx-varnish-manager.sh
T
cschantz 549d2b4d06 Fix Proof of Caching to skip system domains and test direct to server
Changes:
- Filter out system/template domains (cloudvpstemplate, cprapid, IP-based)
- Skip domains under /nobody/ user
- Test directly to server IP using --resolve (bypasses CDN/Cloudflare)
- Show server IP being tested for transparency
- Now correctly finds and tests actual user domains
2026-01-21 22:06:59 -05:00

2181 lines
75 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
################################################################################
# Nginx + Varnish + Apache Caching Manager for cPanel
################################################################################
# Purpose: Complete setup and management of Nginx → Varnish → Apache stack
# Architecture: Client → Nginx (80/443) → Varnish (6081) → Apache (81/444)
# Stock Approach: Uses cPanel's ea-nginx + Apache on default ports
# Only modifies Nginx proxy target (81 → 6081)
# Features:
# - Full automated setup with domain testing
# - Revert/rollback functionality
# - Self-healing diagnostics and auto-fix
# - Smart memory allocation based on server resources
# - Configuration health checks
# - Backup/restore of all configurations
# - cPanel hook for auto-recovery after updates
################################################################################
set -eo pipefail
# Path resolution
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$SCRIPT_DIR/lib/common-functions.sh"
source "$SCRIPT_DIR/lib/system-detect.sh"
source "$SCRIPT_DIR/lib/reference-db.sh"
# Root check
if [ "$EUID" -ne 0 ]; then
print_error "This script must be run as root"
exit 1
fi
# Configuration
BACKUP_DIR="/root/nginx-varnish-backups"
VARNISH_VCL="/etc/varnish/default.vcl"
VARNISH_SERVICE="/usr/lib/systemd/system/varnish.service"
VARNISH_PORT="6081" # Varnish default port (stock)
APACHE_HTTP_PORT="81" # ea-nginx stock port (unchanged)
APACHE_HTTPS_PORT="444" # ea-nginx stock SSL port (unchanged)
NGINX_VENDOR_CONF="/etc/nginx/conf.d/includes-optional/cpanel-proxy-vendors/varnish-proxy.conf"
NGINX_CONFIG_SCRIPT="/etc/nginx/ea-nginx/config-scripts/global/varnish-integration.sh"
# Status indicators
STATUS_FILE="/root/.nginx-varnish-status"
HOOK_SCRIPT="/root/nginx-varnish-hook.sh"
HOOK_LOG="/var/log/nginx-varnish-hook.log"
################################################################################
# HELPER FUNCTIONS
################################################################################
# Check if cPanel Nginx is installed
check_nginx_installed() {
if rpm -q ea-nginx >/dev/null 2>&1; then
return 0
else
return 1
fi
}
# Check if Varnish is installed
check_varnish_installed() {
if rpm -q varnish >/dev/null 2>&1; then
return 0
else
return 1
fi
}
# Check if setup is already configured
check_if_configured() {
if [ -f "$STATUS_FILE" ] && grep -q "CONFIGURED=yes" "$STATUS_FILE" 2>/dev/null; then
return 0
else
return 1
fi
}
# Get total system RAM in MB
get_total_ram_mb() {
free -m | awk '/^Mem:/{print $2}'
}
# Calculate recommended Varnish memory
calculate_varnish_memory() {
local total_ram=$(get_total_ram_mb)
local varnish_mem
# Allocate 10-20% of total RAM for Varnish, with sensible limits
if [ "$total_ram" -lt 2048 ]; then
# Less than 2GB RAM - use 256MB
varnish_mem=256
elif [ "$total_ram" -lt 4096 ]; then
# 2-4GB RAM - use 512MB
varnish_mem=512
elif [ "$total_ram" -lt 8192 ]; then
# 4-8GB RAM - use 1GB
varnish_mem=1024
elif [ "$total_ram" -lt 16384 ]; then
# 8-16GB RAM - use 2GB
varnish_mem=2048
else
# 16GB+ RAM - use 4GB
varnish_mem=4096
fi
echo "$varnish_mem"
}
# Create backup with timestamp
create_backup() {
local timestamp=$(date +%Y%m%d_%H%M%S)
local backup_path="$BACKUP_DIR/backup_$timestamp"
# Check disk space before backup
local available_space=$(df /root | tail -1 | awk '{print $4}')
if [ "$available_space" -lt 51200 ]; then
print_error "Insufficient disk space for backup (less than 50MB available)"
return 1
fi
mkdir -p "$backup_path"
# Backup Nginx configs if they exist
if [ -f /etc/nginx/ea-nginx.conf ]; then
cp -a /etc/nginx/ea-nginx.conf "$backup_path/" 2>/dev/null || true
fi
if [ -d /etc/nginx/conf.d ]; then
cp -a /etc/nginx/conf.d "$backup_path/" 2>/dev/null || true
fi
if [ -d /etc/nginx/ea-nginx ]; then
cp -a /etc/nginx/ea-nginx "$backup_path/" 2>/dev/null || true
fi
# Backup Varnish configs if they exist
if [ -f /etc/varnish/default.vcl ]; then
cp -a /etc/varnish/default.vcl "$backup_path/" 2>/dev/null || true
fi
if [ -f /usr/lib/systemd/system/varnish.service ]; then
cp -a /usr/lib/systemd/system/varnish.service "$backup_path/" 2>/dev/null || true
fi
# Backup Apache configs
if [ -f /var/cpanel/cpanel.config ]; then
cp -a /var/cpanel/cpanel.config "$backup_path/" 2>/dev/null || true
fi
echo "$backup_path"
}
# Get list of cPanel domains
get_cpanel_domains() {
local domains=()
# Get domains from cPanel user data
if [ -d /var/cpanel/userdata ]; then
while IFS= read -r domain_file; do
local domain=$(basename "$domain_file")
# Skip cache files, main file, and config files
if [[ "$domain_file" =~ \.cache$ ]] || \
[[ "$domain_file" =~ /cache$ ]] || \
[[ "$domain_file" =~ /main$ ]] || \
[[ "$domain" =~ _SSL$ ]] || \
[[ "$domain" =~ \.yaml$ ]] || \
[[ "$domain" =~ \.json$ ]] || \
[[ "$domain" =~ \.conf$ ]] || \
[[ "$domain" =~ \.backup$ ]]; then
continue
fi
# Skip system/template domains
if [[ "$domain" =~ cloudvpstemplate\. ]] || \
[[ "$domain" =~ cprapid\. ]] || \
[[ "$domain" =~ ^[0-9\-]+\. ]] || \
[[ "$domain_file" =~ /nobody/ ]]; then
continue
fi
# Only add if it looks like a domain (has a dot, not . or ..)
if [[ "$domain" != "." && "$domain" != ".." && "$domain" =~ \. ]]; then
domains+=("$domain")
fi
done < <(find /var/cpanel/userdata -type f 2>/dev/null | head -50)
fi
printf '%s\n' "${domains[@]}"
}
# Check if cPanel hook is registered
check_hook_registered() {
if [ -f /usr/local/cpanel/bin/manage_hooks ]; then
if /usr/local/cpanel/bin/manage_hooks list 2>/dev/null | grep -q "nginx-varnish-hook.sh"; then
return 0
fi
fi
return 1
}
# Modify ea-nginx settings.json to use Varnish port
modify_settings_json() {
local settings_file="/etc/nginx/ea-nginx/settings.json"
print_info "Modifying ea-nginx settings.json to use Varnish port..."
# Backup original settings.json
if [ ! -f "${settings_file}.stock" ]; then
cp "$settings_file" "${settings_file}.stock"
print_info "Original settings.json backed up to ${settings_file}.stock"
fi
# ============================================================================
# HTTP + HTTPS Caching Configuration
# ============================================================================
# Strategy: SSL termination at Nginx, HTTP backends to Varnish
#
# How it works:
# 1. settings.json sets apache_port to 6081 (Varnish) for HTTP traffic
# 2. ea-nginx generates config with $scheme://apache_backend_${scheme}_...
# 3. Config-script post-processes to force HTTP protocol for all backends
# 4. Result: SSL terminates at Nginx, all backend traffic uses HTTP to Varnish
#
# Architecture:
# - Client → Nginx (SSL termination for HTTPS) → Varnish → Apache (all HTTP)
# - HTTP: Client:80 → Nginx:80 → Varnish:6081 → Apache:81 [CACHED]
# - HTTPS: Client:443 → Nginx:443 (SSL) → Varnish:6081 (HTTP) → Apache:81 [CACHED]
#
# Note: Config-script at /etc/nginx/ea-nginx/config-scripts/global/ runs after
# every ea-nginx rebuild to maintain the HTTP backend override.
# ============================================================================
cat > "$settings_file" <<EOFSETTINGS
{
"apache_port" : "6081",
"apache_port_ip" : "127.0.0.1",
"apache_ssl_port" : "444",
"apache_ssl_port_ip" : "127.0.0.1",
"client_max_body_size" : "128m"
}
EOFSETTINGS
if grep -q '"apache_port" : "6081"' "$settings_file"; then
print_success "settings.json updated successfully"
echo ""
print_info "Configuration Applied:"
print_info " • HTTP traffic (port 80) → Varnish:6081 → Apache:81 [CACHED]"
print_info " • HTTPS traffic (port 443) → Varnish:6081 → Apache:81 [CACHED]"
echo ""
print_success "Both HTTP and HTTPS will be cached by Varnish"
print_info " Method: SSL termination at Nginx, HTTP backends to Varnish"
print_info " Safety: Config-script maintains configuration after ea-nginx rebuilds"
return 0
else
print_error "Failed to update settings.json"
return 1
fi
}
# Restore ea-nginx settings.json to stock
restore_settings_json() {
local settings_file="/etc/nginx/ea-nginx/settings.json"
print_info "Restoring ea-nginx settings.json to stock configuration..."
if [ -f "${settings_file}.stock" ]; then
cp "${settings_file}.stock" "$settings_file"
rm -f "${settings_file}.stock"
print_success "settings.json restored to stock (port 81)"
else
# Create stock settings if backup doesn't exist
cat > "$settings_file" <<EOFSETTINGS
{
"apache_port" : "81",
"apache_port_ip" : "127.0.0.1",
"apache_ssl_port" : "444",
"apache_ssl_port_ip" : "127.0.0.1",
"client_max_body_size" : "128m"
}
EOFSETTINGS
print_success "settings.json reset to stock defaults"
fi
return 0
}
# Create ea-nginx config script for automatic recovery
create_eanginx_config_script() {
local config_script="/etc/nginx/ea-nginx/config-scripts/global/config-scripts-global-varnish"
print_info "Creating ea-nginx config script for automatic recovery..."
# Ensure directory exists
mkdir -p /etc/nginx/ea-nginx/config-scripts/global
# Create the config script
cat > "$config_script" <<'EOFSCRIPT'
#!/bin/bash
################################################################################
# ea-nginx Global Config Script: Varnish Proxy Auto-Fix
################################################################################
# Purpose: Automatically re-apply Varnish proxy configuration after ea-nginx
# config regeneration (runs every time ea-nginx config --global runs)
# Location: /etc/nginx/ea-nginx/config-scripts/global/
# Triggered by: ea-nginx config --global, ea-nginx config --all, cPanel updates
################################################################################
NGINX_CONF="/etc/nginx/conf.d/ea-nginx.conf"
STATUS_FILE="/root/.nginx-varnish-status"
LOG_FILE="/var/log/nginx-varnish-hook.log"
# Logging function
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ea-nginx-config-script] $1" >> "$LOG_FILE"
}
log_message "=== ea-nginx Config Script Triggered ==="
# Check if Varnish integration is configured
if [ ! -f "$STATUS_FILE" ] || ! grep -q "CONFIGURED=yes" "$STATUS_FILE" 2>/dev/null; then
log_message "Varnish not configured. Skipping."
exit 0
fi
log_message "Varnish integration detected. Checking Nginx configuration..."
# Check if nginx conf exists
if [ ! -f "$NGINX_CONF" ]; then
log_message "ERROR: Nginx config file not found at $NGINX_CONF"
exit 0
fi
# Check if configuration needs fixing (ea-nginx regenerated it to stock port 81)
if grep -q "^\s*default\s\+81\s*;" "$NGINX_CONF" 2>/dev/null; then
log_message "DETECTED: ea-nginx.conf regenerated with stock port 81. Re-applying Varnish proxy (port 6081)..."
# Re-apply proxy port change to Varnish
if sed -i 's/^\(\s*default\s\+\)81\s*;/\16081;/' "$NGINX_CONF" 2>/dev/null; then
log_message "SUCCESS: Proxy port changed to 6081 (Varnish)"
else
log_message "ERROR: Failed to change proxy port to 6081"
fi
else
log_message "Configuration already correct (points to port 6081). No action needed."
fi
# ============================================================================
# Force HTTPS traffic to use HTTP backend protocol (enables HTTPS caching)
# ============================================================================
# This processes all per-domain configs to force HTTP backend for both
# HTTP and HTTPS traffic. Without this, HTTPS bypasses Varnish.
#
# Original: $scheme://apache_backend_${scheme}_IP (HTTP->HTTP, HTTPS->HTTPS)
# Modified: http://apache_backend_http_IP (both use HTTP backend)
# ============================================================================
log_message "Processing per-domain configs to force HTTP backend for HTTPS..."
domain_count=0
modified_count=0
# Process all per-domain config files
for config_file in /etc/nginx/conf.d/users/*.conf; do
[ -f "$config_file" ] || continue
domain_count=$((domain_count + 1))
# Check if this domain needs fixing (uses scheme-based backend)
if grep -q '\$scheme://apache_backend_\${scheme}_' "$config_file" 2>/dev/null; then
# Force HTTP backend protocol for all traffic (enables HTTPS caching)
if sed -i 's|\$scheme://apache_backend_\${\?scheme\?}_|http://apache_backend_http_|g' "$config_file" 2>/dev/null; then
modified_count=$((modified_count + 1))
fi
fi
done
if [ $modified_count -gt 0 ]; then
log_message "SUCCESS: Modified $modified_count of $domain_count domain configs to use HTTP backend"
log_message "HTTPS traffic now routes through Varnish (SSL terminates at Nginx, HTTP to backend)"
else
log_message "All $domain_count domain configs already use HTTP backend. No changes needed."
fi
log_message "=== Config Script Completed ==="
exit 0
EOFSCRIPT
chmod +x "$config_script"
if [ -f "$config_script" ] && [ -x "$config_script" ]; then
print_success "ea-nginx config script created successfully"
print_info "Script will auto-fix proxy port after ANY ea-nginx rebuild"
return 0
else
print_error "Failed to create ea-nginx config script"
return 1
fi
}
# Remove ea-nginx config script
remove_eanginx_config_script() {
local config_script="/etc/nginx/ea-nginx/config-scripts/global/config-scripts-global-varnish"
if [ -f "$config_script" ]; then
print_info "Removing ea-nginx config script..."
rm -f "$config_script"
print_success "ea-nginx config script removed"
fi
return 0
}
################################################################################
# INSTALLATION FUNCTIONS
################################################################################
# Install cPanel Nginx
install_cpanel_nginx() {
print_banner "Installing cPanel Nginx"
# Fix hostname resolution for Apache RemoteIPInternalProxy
local server_hostname=$(hostname -f 2>/dev/null || hostname)
if [ -n "$server_hostname" ]; then
if ! grep -q "127.0.0.1.*$server_hostname" /etc/hosts 2>/dev/null; then
echo "Adding hostname to /etc/hosts for Apache configuration..."
echo "127.0.0.1 $server_hostname" >> /etc/hosts
print_info "Added $server_hostname to /etc/hosts"
fi
fi
echo ""
echo "Installing ea-nginx package..."
if yum install -y ea-nginx; then
print_success "ea-nginx installed successfully"
else
print_error "Failed to install ea-nginx"
return 1
fi
echo ""
echo "Rebuilding HTTP configuration..."
if /scripts/rebuildhttpdconf; then
print_success "HTTP configuration rebuilt"
else
print_error "Failed to rebuild HTTP configuration"
return 1
fi
echo ""
echo "Enabling and starting Nginx..."
systemctl enable nginx
systemctl restart nginx
if systemctl is-active --quiet nginx; then
print_success "Nginx is running"
else
print_error "Nginx failed to start"
return 1
fi
return 0
}
# Install Varnish
install_varnish() {
print_banner "Installing Varnish Cache"
echo "Installing Varnish 6.6 from AlmaLinux repositories..."
echo "(Varnish 6.6 with VCL 4.1 support is fully compatible)"
echo ""
if yum install -y varnish; then
local varnish_version=$(varnishd -V 2>&1 | head -1)
print_success "Varnish installed successfully"
echo " Version: $varnish_version"
else
print_error "Failed to install Varnish"
return 1
fi
systemctl enable varnish
return 0
}
# Configure Varnish VCL
configure_varnish_vcl() {
print_banner "Configuring Varnish VCL"
# Get server's primary IP address for Apache backend
local server_ip=$(hostname -I | awk '{print $1}')
if [ -z "$server_ip" ]; then
server_ip="127.0.0.1"
print_warning "Could not detect server IP, using 127.0.0.1"
else
print_info "Detected server IP: $server_ip"
fi
# Simple VCL with comprehensive admin page bypasses
cat > "$VARNISH_VCL" <<'EOFVCL'
vcl 4.1;
# Backend definition - Apache on port 81 (ea-nginx stock port)
backend default {
.host = "SERVER_IP_PLACEHOLDER";
.port = "81";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
}
sub vcl_recv {
# Normalize the host header
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
# CRITICAL: AutoSSL / Let's Encrypt - Don't cache SSL validation
if (req.url ~ "^/\.well-known/acme-challenge/") {
return (pass);
}
# CRITICAL: cPanel Services - Don't cache cPanel admin interfaces
if (req.http.Host ~ "^(cpanel|webmail|whm|cpcalendars|cpcontacts)\." ||
req.http.Host ~ ":2082$" ||
req.http.Host ~ ":2083$" ||
req.http.Host ~ ":2086$" ||
req.http.Host ~ ":2087$") {
return (pipe);
}
# Don't cache admin/login pages for common CMSs and admin panels
if (req.url ~ "^/wp-admin" ||
req.url ~ "^/wp-login\.php" ||
req.url ~ "^/administrator" ||
req.url ~ "^/admin" ||
req.url ~ "^/user/login" ||
req.url ~ "^/cpanel" ||
req.url ~ "^/webmail" ||
req.url ~ "^/whm" ||
req.url ~ "^/phpmyadmin" ||
req.url ~ "^/pma" ||
req.url ~ "^/roundcube" ||
req.url ~ "^/horde" ||
req.url ~ "^/squirrelmail") {
return (pass);
}
# Don't cache POST requests
if (req.method == "POST") {
return (pass);
}
# Don't cache requests with cookies (except static files)
if (req.http.Cookie && req.url !~ "\.(jpg|jpeg|jpe|gif|png|ico|bmp|tif|tiff|svg|svgz|webp|avif|heic|heif|jfif|pjpeg|pjp|apng|css|js|mjs|map|woff|woff2|ttf|otf|eot|zip|tgz|gz|tar|rar|bz2|7z|xz|lz|lzma|pdf|txt|rtf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odp|csv|xml|json|mp3|mp4|m4a|m4v|ogg|oga|ogv|webm|wav|flac|aac|wma|opus|mid|midi|avi|mov|wmv|flv|mkv|mpeg|mpg|3gp|3g2|m2v|ts|m3u8|swf|html|htm|wasm|manifest|appcache|bin|exe|msi|dmg|iso|deb|rpm|cab)$") {
return (pass);
}
# Cache static files - remove cookies
if (req.url ~ "\.(jpg|jpeg|jpe|gif|png|ico|bmp|tif|tiff|svg|svgz|webp|avif|heic|heif|jfif|pjpeg|pjp|apng|css|js|mjs|map|woff|woff2|ttf|otf|eot|zip|tgz|gz|tar|rar|bz2|7z|xz|lz|lzma|pdf|txt|rtf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odp|csv|xml|json|mp3|mp4|m4a|m4v|ogg|oga|ogv|webm|wav|flac|aac|wma|opus|mid|midi|avi|mov|wmv|flv|mkv|mpeg|mpg|3gp|3g2|m2v|ts|m3u8|swf|html|htm|wasm|manifest|appcache|bin|exe|msi|dmg|iso|deb|rpm|cab)$") {
unset req.http.Cookie;
return (hash);
}
# Default: try to serve from cache
return (hash);
}
sub vcl_backend_fetch {
# CRITICAL: Preserve Host header for Apache VirtualHost routing
# Without this, Apache receives IP address and serves wrong VirtualHost
if (bereq.http.Host) {
set bereq.http.Host = bereq.http.Host;
}
}
sub vcl_backend_response {
# Add identifying header
set beresp.http.X-Served-By = "Varnish";
# Cache static files for 1 hour
if (bereq.url ~ "\.(jpg|jpeg|jpe|gif|png|ico|bmp|tif|tiff|svg|svgz|webp|avif|heic|heif|jfif|pjpeg|pjp|apng|css|js|mjs|map|woff|woff2|ttf|otf|eot|zip|tgz|gz|tar|rar|bz2|7z|xz|lz|lzma|pdf|txt|rtf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odp|csv|xml|json|mp3|mp4|m4a|m4v|ogg|oga|ogv|webm|wav|flac|aac|wma|opus|mid|midi|avi|mov|wmv|flv|mkv|mpeg|mpg|3gp|3g2|m2v|ts|m3u8|swf|html|htm|wasm|manifest|appcache|bin|exe|msi|dmg|iso|deb|rpm|cab)$") {
set beresp.ttl = 1h;
unset beresp.http.Set-Cookie;
}
# Don't cache if Set-Cookie is present (dynamic content)
if (beresp.http.Set-Cookie) {
set beresp.ttl = 0s;
set beresp.uncacheable = true;
return (deliver);
}
# Cache 404s for a short time to reduce backend load
if (beresp.status == 404) {
set beresp.ttl = 60s;
}
# Don't cache 5xx errors
if (beresp.status >= 500) {
set beresp.ttl = 0s;
set beresp.uncacheable = true;
return (deliver);
}
return (deliver);
}
sub vcl_deliver {
# Add cache status header for debugging
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache = "MISS";
}
# Keep the Varnish identifier
set resp.http.X-Served-By = "Varnish";
# Remove internal headers before sending to client
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Age;
return (deliver);
}
EOFVCL
# Replace placeholder with actual server IP
sed -i "s/SERVER_IP_PLACEHOLDER/$server_ip/g" "$VARNISH_VCL"
# Test VCL configuration
# Note: /tmp is usually mounted with noexec on cPanel servers, so use -n parameter
# to specify a working directory outside /tmp
mkdir -p /var/lib/varnish/test
if varnishd -n /var/lib/varnish/test -C -f "$VARNISH_VCL" >/dev/null 2>&1; then
print_success "VCL configuration is valid"
return 0
else
print_error "VCL configuration is invalid"
return 1
fi
}
# Configure Varnish to listen on port 81
configure_varnish_port() {
local varnish_mem="${1:-256}"
print_banner "Configuring Varnish Port and Memory"
echo "Setting Varnish to listen on port $VARNISH_PORT with ${varnish_mem}m RAM..."
# Create systemd override directory
mkdir -p /etc/systemd/system/varnish.service.d/
# Create override configuration
cat > /etc/systemd/system/varnish.service.d/override.conf <<EOFSERVICE
[Service]
ExecStart=
ExecStart=/usr/sbin/varnishd -a :${VARNISH_PORT} -f /etc/varnish/default.vcl -s malloc,${varnish_mem}m
EOFSERVICE
systemctl daemon-reload
print_success "Varnish configured to use port $VARNISH_PORT with ${varnish_mem}m RAM"
return 0
}
# Configure Nginx to proxy to Varnish
configure_nginx_varnish_proxy() {
print_banner "Configuring Nginx to Proxy to Varnish"
# With settings.json approach, we just rebuild ea-nginx config
# ea-nginx reads settings.json (with apache_port = 6081) and generates correct config
echo "Rebuilding ea-nginx configuration from settings.json..."
if /usr/local/cpanel/scripts/ea-nginx config --global >/dev/null 2>&1; then
print_success "ea-nginx configuration rebuilt"
else
print_warning "ea-nginx rebuild encountered issues (may still work)"
fi
# Verify the generated config
local nginx_conf="/etc/nginx/conf.d/ea-nginx.conf"
if grep -q "default 6081;" "$nginx_conf" 2>/dev/null; then
print_success "Nginx configured to proxy to Varnish (port 6081)"
else
print_warning "Proxy port may not be correct - check ea-nginx.conf"
fi
# Test Nginx configuration
if nginx -t >/dev/null 2>&1; then
print_success "Nginx configuration is valid"
return 0
else
print_error "Nginx configuration test failed"
nginx -t 2>&1 | tail -5
return 1
fi
}
# Test domain accessibility
test_domain() {
local domain="$1"
local protocol="$2"
local url="${protocol}://${domain}"
local response=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$url" 2>/dev/null || echo "000")
local varnish_header=$(curl -s -I --max-time 5 "$url" 2>/dev/null | grep -i "X-Served-By" | grep -i "Varnish" || true)
if [ "$response" = "200" ] || [ "$response" = "301" ] || [ "$response" = "302" ]; then
if [ -n "$varnish_header" ]; then
echo "$domain ($protocol): $response - Varnish active"
return 0
else
echo "$domain ($protocol): $response - No Varnish header"
return 0 # Don't crash the script
fi
else
echo "$domain ($protocol): $response"
return 1
fi
}
# Quick proof that caching is actually working
proof_of_caching() {
print_banner "Proof of Caching Test"
echo "This test proves caching is working by showing MISS → HIT pattern"
echo ""
# Get first domain
local domain=$(get_cpanel_domains | head -1)
if [ -z "$domain" ]; then
print_error "No domains found to test"
echo ""
echo "Tip: Make sure you have at least one active domain/website configured"
return 0
fi
# Get server IP for direct testing (bypasses CDN)
local server_ip=$(hostname -I | awk '{print $1}')
echo "Testing domain: $domain"
echo "Server IP: $server_ip (testing direct to bypass CDN)"
echo ""
# Test common static files
local test_files=(
"/robots.txt"
"/favicon.ico"
"/"
)
local cache_working=0
for test_path in "${test_files[@]}"; do
local url="http://${domain}${test_path}"
echo "Testing: $test_path"
# First request - should be MISS
# Use --resolve to bypass CDN and test directly to server
local first_request=$(curl -s -I --max-time 5 --resolve "${domain}:80:${server_ip}" "$url" 2>/dev/null)
local first_cache=$(echo "$first_request" | grep -i "X-Cache:" | awk '{print $2}' | tr -d '\r')
# Second request - should be HIT
sleep 0.5
local second_request=$(curl -s -I --max-time 5 --resolve "${domain}:80:${server_ip}" "$url" 2>/dev/null)
local second_cache=$(echo "$second_request" | grep -i "X-Cache:" | awk '{print $2}' | tr -d '\r')
# Check if we got valid responses
if [ -z "$first_cache" ] || [ -z "$second_cache" ]; then
echo " Status: Skipped (no cache headers)"
echo ""
continue
fi
# Display results
echo " Request 1: X-Cache: $first_cache"
echo " Request 2: X-Cache: $second_cache"
# Check if caching worked
if [ "$first_cache" = "MISS" ] && [ "$second_cache" = "HIT" ]; then
print_success " ✓ CACHING WORKS! (MISS → HIT)"
cache_working=1
elif [ "$second_cache" = "HIT" ]; then
print_success " ✓ Cache HIT detected"
cache_working=1
elif [ "$first_cache" = "MISS" ] && [ "$second_cache" = "MISS" ]; then
print_warning " ⚠ No caching (both MISS) - may be dynamic content"
else
print_info " Status: $first_cache$second_cache"
fi
echo ""
done
echo "════════════════════════════════════════════════════════════"
if [ "$cache_working" -eq 1 ]; then
echo ""
print_success "✓ PROOF CONFIRMED: Varnish is caching your sites!"
echo ""
echo "What this means:"
echo " • Static files are being cached by Varnish"
echo " • Repeat visitors get instant responses from cache"
echo " • Server load is reduced for cached content"
echo ""
else
echo ""
print_warning "⚠ Could not confirm caching"
echo ""
echo "Possible reasons:"
echo " • Tested URLs are dynamic (admin pages, etc.)"
echo " • Cache was already populated (no MISS seen)"
echo " • Try option 7 to clear cache, then test again"
echo ""
fi
return 0
}
################################################################################
# DIAGNOSTIC FUNCTIONS
################################################################################
# Run comprehensive diagnostics
run_diagnostics() {
print_banner "Nginx + Varnish Health Check"
local issues_found=0
echo "Checking service status..."
echo ""
# Check Nginx
if systemctl is-active --quiet nginx; then
print_success "Nginx is running"
else
print_error "Nginx is not running"
issues_found=$((issues_found + 1))
fi
# Check Varnish
if systemctl is-active --quiet varnish; then
print_success "Varnish is running"
# Check if enabled for auto-start on boot
if ! systemctl is-enabled --quiet varnish 2>/dev/null; then
print_warning "Varnish is NOT enabled (won't start on reboot)"
print_info " Run 'Auto-Fix Issues' to enable auto-start"
issues_found=$((issues_found + 1))
fi
else
print_error "Varnish is not running"
issues_found=$((issues_found + 1))
fi
# Check Apache
if systemctl is-active --quiet httpd; then
print_success "Apache is running"
else
print_error "Apache is not running"
issues_found=$((issues_found + 1))
fi
echo ""
echo "Checking port configuration..."
echo ""
# Check ports using ss (more reliable) or netstat as fallback
if command -v ss >/dev/null 2>&1; then
# Use ss if available
if ss -tlnp 2>/dev/null | grep -E ":80\s.*nginx" >/dev/null; then
print_success "Nginx listening on port 80"
else
print_error "Nginx not listening on port 80"
issues_found=$((issues_found + 1))
fi
if ss -tlnp 2>/dev/null | grep -E ":443\s.*nginx" >/dev/null; then
print_success "Nginx listening on port 443"
else
print_error "Nginx not listening on port 443"
issues_found=$((issues_found + 1))
fi
if ss -tlnp 2>/dev/null | grep -E ":${VARNISH_PORT}\s.*varnish" >/dev/null; then
print_success "Varnish listening on port $VARNISH_PORT"
else
print_error "Varnish not listening on port $VARNISH_PORT"
issues_found=$((issues_found + 1))
fi
if ss -tlnp 2>/dev/null | grep -E ":${APACHE_HTTP_PORT}\s.*httpd" >/dev/null; then
print_success "Apache listening on port $APACHE_HTTP_PORT"
else
print_error "Apache not listening on port $APACHE_HTTP_PORT"
issues_found=$((issues_found + 1))
fi
else
# Fallback to netstat with better patterns
if netstat -tlnp 2>/dev/null | awk '$4 ~ /:80$/ && $7 ~ /nginx/' | head -1 | grep -q .; then
print_success "Nginx listening on port 80"
else
print_error "Nginx not listening on port 80"
issues_found=$((issues_found + 1))
fi
if netstat -tlnp 2>/dev/null | awk '$4 ~ /:443$/ && $7 ~ /nginx/' | head -1 | grep -q .; then
print_success "Nginx listening on port 443"
else
print_error "Nginx not listening on port 443"
issues_found=$((issues_found + 1))
fi
if netstat -tlnp 2>/dev/null | awk -v port="$VARNISH_PORT" '$4 ~ ":"port"$" && $7 ~ /varnish/' | head -1 | grep -q .; then
print_success "Varnish listening on port $VARNISH_PORT"
else
print_error "Varnish not listening on port $VARNISH_PORT"
issues_found=$((issues_found + 1))
fi
if netstat -tlnp 2>/dev/null | awk -v port="$APACHE_HTTP_PORT" '$4 ~ ":"port"$" && $7 ~ /httpd/' | head -1 | grep -q .; then
print_success "Apache listening on port $APACHE_HTTP_PORT"
else
print_error "Apache not listening on port $APACHE_HTTP_PORT"
issues_found=$((issues_found + 1))
fi
fi
echo ""
echo "Checking configuration files..."
echo ""
# Check VCL - use varnishadm instead of varnishd -C (more reliable)
if [ -f "$VARNISH_VCL" ]; then
if varnishadm vcl.list 2>/dev/null | grep -q "active.*warm"; then
print_success "Varnish VCL is loaded and active"
else
print_warning "Varnish VCL may not be active"
issues_found=$((issues_found + 1))
fi
else
print_error "Varnish VCL file not found"
issues_found=$((issues_found + 1))
fi
# Check Nginx config
if nginx -t 2>&1 | grep -q "successful"; then
print_success "Nginx configuration is valid"
else
print_error "Nginx configuration has errors"
issues_found=$((issues_found + 1))
fi
# Check settings.json configuration
if [ -f /etc/nginx/ea-nginx/settings.json ]; then
if grep -q "\"apache_port\" : \"${VARNISH_PORT}\"" /etc/nginx/ea-nginx/settings.json; then
print_success "settings.json configured for Varnish (port ${VARNISH_PORT})"
else
print_error "settings.json not configured for Varnish"
issues_found=$((issues_found + 1))
fi
else
print_error "settings.json not found"
issues_found=$((issues_found + 1))
fi
# Check ea-nginx.conf proxy configuration for HTTP
if [ -f /etc/nginx/conf.d/ea-nginx.conf ]; then
if grep -q "default ${VARNISH_PORT};" /etc/nginx/conf.d/ea-nginx.conf; then
print_success "ea-nginx.conf proxies HTTP to Varnish (port ${VARNISH_PORT})"
else
print_warning "ea-nginx.conf may not be proxying to Varnish"
issues_found=$((issues_found + 1))
fi
# Check HTTPS configuration
if grep -q "\"apache_ssl_port\" : \"444\"" /etc/nginx/ea-nginx/settings.json 2>/dev/null; then
print_success "HTTPS backend configured correctly (Apache:444)"
print_info " Note: Config-script forces HTTP protocol for Varnish caching"
# Verify config-script has applied HTTP backend override
if grep -q 'set $CPANEL_APACHE_PROXY_PASS http://apache_backend_http_' /etc/nginx/conf.d/users/*.conf 2>/dev/null; then
print_success " ✓ HTTPS traffic routed through Varnish (HTTP protocol)"
else
print_warning " ⚠ Config-script override not detected - HTTPS may not cache"
print_info " Run 'Auto-Fix Issues' to apply config-script"
issues_found=$((issues_found + 1))
fi
fi
else
print_error "ea-nginx.conf not found"
issues_found=$((issues_found + 1))
fi
echo ""
echo "Checking Varnish backend health..."
echo ""
if command -v varnishadm >/dev/null 2>&1; then
if varnishadm backend.list 2>/dev/null | grep -qi "healthy"; then
print_success "Varnish backend is healthy"
else
print_warning "Varnish backend may not be healthy"
issues_found=$((issues_found + 1))
fi
fi
echo ""
echo "Checking configuration persistence..."
echo ""
# Check if config-script safety net exists
if [ -f /etc/nginx/ea-nginx/config-scripts/global/config-scripts-global-varnish ]; then
print_success "Config-script safety net installed"
print_info " Auto-fixes if settings.json is overwritten"
else
print_info "Config-script safety net not installed"
print_info " Configuration relies on settings.json RPM preservation"
fi
echo ""
echo "════════════════════════════════════════════════════════════"
if [ "$issues_found" -eq 0 ]; then
print_success "All checks passed! Configuration is healthy."
else
print_warning "Found $issues_found issue(s) that may need attention"
fi
# Always return 0 - finding issues is not a failure, it's information
return 0
}
# Auto-fix common issues
auto_fix_issues() {
print_banner "Self-Healing: Auto-Fixing Common Issues"
local fixes_applied=0
echo "Checking for common issues and applying fixes..."
echo ""
# Fix 1: Restart services if not running
if ! systemctl is-active --quiet varnish; then
echo "Fixing: Varnish is not running..."
if systemctl restart varnish; then
print_success "Restarted Varnish"
fixes_applied=$((fixes_applied + 1))
else
print_error "Failed to restart Varnish"
fi
fi
if ! systemctl is-active --quiet nginx; then
echo "Fixing: Nginx is not running..."
if systemctl restart nginx; then
print_success "Restarted Nginx"
fixes_applied=$((fixes_applied + 1))
else
print_error "Failed to restart Nginx"
fi
fi
# Fix 1b: Enable Varnish for auto-start on boot
if ! systemctl is-enabled --quiet varnish 2>/dev/null; then
echo "Fixing: Varnish not enabled for auto-start on boot..."
if systemctl enable varnish; then
print_success "Enabled Varnish (will start on boot)"
fixes_applied=$((fixes_applied + 1))
else
print_error "Failed to enable Varnish"
fi
fi
# Fix 1c: Verify config-script is applying HTTP backend override for HTTPS
if ! grep -q 'set $CPANEL_APACHE_PROXY_PASS http://apache_backend_http_' /etc/nginx/conf.d/users/*.conf 2>/dev/null; then
echo "Fixing: HTTPS not configured to use Varnish..."
echo " Running config-script to force HTTP backend protocol..."
# Run the config-script
if bash /etc/nginx/ea-nginx/config-scripts/global/config-scripts-global-varnish 2>/dev/null; then
print_success "Applied HTTP backend override for HTTPS traffic"
print_info " HTTPS now routes through Varnish using HTTP protocol"
fixes_applied=$((fixes_applied + 1))
else
print_error "Failed to run config-script"
fi
fi
# Fix 2: Check if settings.json has wrong port
if [ -f /etc/nginx/ea-nginx/settings.json ]; then
if grep -q '"apache_port" : "81"' /etc/nginx/ea-nginx/settings.json 2>/dev/null; then
echo "Fixing: settings.json has stock port (81) instead of Varnish (6081)..."
if modify_settings_json; then
print_success "Fixed settings.json (port 6081)"
# Rebuild ea-nginx config
/usr/local/cpanel/scripts/ea-nginx config --global >/dev/null 2>&1
systemctl reload nginx
fixes_applied=$((fixes_applied + 1))
fi
fi
fi
# Fix 3: Check if ea-nginx.conf has wrong port despite settings.json being correct
if [ -f /etc/nginx/conf.d/ea-nginx.conf ]; then
if grep -q "default 81;" /etc/nginx/conf.d/ea-nginx.conf 2>/dev/null; then
# Check if settings.json is correct first
if grep -q '"apache_port" : "6081"' /etc/nginx/ea-nginx/settings.json 2>/dev/null; then
echo "Fixing: ea-nginx.conf has wrong port, rebuilding from settings.json..."
/usr/local/cpanel/scripts/ea-nginx config --global >/dev/null 2>&1
systemctl reload nginx
print_success "Rebuilt ea-nginx.conf from settings.json"
fixes_applied=$((fixes_applied + 1))
fi
fi
fi
# Fix 4: Reload systemd if Varnish service override exists but daemon not reloaded
if [ -f /etc/systemd/system/varnish.service.d/override.conf ]; then
if ! systemctl is-active --quiet varnish; then
systemctl daemon-reload
print_success "Reloaded systemd configuration"
fixes_applied=$((fixes_applied + 1))
fi
fi
# Fix 5: Rebuild HTTP conf if Nginx config is broken
if ! nginx -t >/dev/null 2>&1; then
echo "Fixing: Nginx configuration errors..."
if /scripts/rebuildhttpdconf; then
# After rebuild, ensure settings.json config is applied
if grep -q '"apache_port" : "6081"' /etc/nginx/ea-nginx/settings.json 2>/dev/null; then
/usr/local/cpanel/scripts/ea-nginx config --global >/dev/null 2>&1
fi
systemctl reload nginx
print_success "Rebuilt Nginx configuration"
fixes_applied=$((fixes_applied + 1))
fi
fi
# Fix 6: Recreate config-script if missing (safety net)
if [ -f "$STATUS_FILE" ] && grep -q "CONFIGURED=yes" "$STATUS_FILE"; then
if [ ! -f /etc/nginx/ea-nginx/config-scripts/global/config-scripts-global-varnish ]; then
echo "Fixing: ea-nginx config-script missing, recreating..."
if create_eanginx_config_script; then
print_success "Recreated config-script safety net"
fixes_applied=$((fixes_applied + 1))
fi
fi
fi
# Fix 7: Restore settings.json.stock backup if settings.json is missing
if [ ! -f /etc/nginx/ea-nginx/settings.json ] && [ -f /etc/nginx/ea-nginx/settings.json.stock ]; then
echo "Fixing: settings.json missing, restoring from backup..."
cp /etc/nginx/ea-nginx/settings.json.stock /etc/nginx/ea-nginx/settings.json
# Rebuild ea-nginx config
/usr/local/cpanel/scripts/ea-nginx config --global >/dev/null 2>&1
systemctl reload nginx
print_success "Restored settings.json from backup"
fixes_applied=$((fixes_applied + 1))
fi
echo ""
if [ "$fixes_applied" -gt 0 ]; then
print_success "Applied $fixes_applied fix(es)"
else
print_info "No fixes needed"
fi
return 0
}
################################################################################
# MAIN SETUP FUNCTION
################################################################################
full_setup() {
print_banner "Complete Nginx + Varnish Setup"
echo "This will install and configure the complete caching stack:"
echo ""
echo " Stock Apache → ea-nginx (Reverse Proxy) + Varnish (Cache) + Apache"
echo ""
echo "Components to be installed:"
echo " 1. ea-nginx - Nginx reverse proxy (if not already installed)"
echo " 2. Varnish Cache - HTTP accelerator"
echo " 3. Complete stack configuration"
echo ""
echo "Traffic flow:"
echo " Client → Nginx (80/443) → Varnish (6081) → Apache (81/444)"
echo ""
print_warning "⚠ IMPORTANT:"
print_warning " • This is NOT officially supported by cPanel"
print_warning " • Use 'Revert Setup' to completely remove and return to stock Apache"
print_warning " • Revert will remove BOTH Nginx and Varnish"
echo ""
read -p "Continue with complete stack installation? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Installation cancelled."
press_enter
return 0
fi
# Create backup first
echo ""
print_info "Creating backup of current configuration..."
local backup_path=$(create_backup)
print_success "Backup created at: $backup_path"
# Calculate recommended Varnish memory
local total_ram=$(get_total_ram_mb)
local recommended_mem=$(calculate_varnish_memory)
echo ""
echo "Server RAM: ${total_ram}MB"
echo "Recommended Varnish memory: ${recommended_mem}MB"
echo ""
# Step 1: Install cPanel Nginx if not already installed
if ! check_nginx_installed; then
echo ""
print_info "Step 1/5: Installing cPanel Nginx..."
if ! install_cpanel_nginx; then
print_error "Setup failed at Step 1"
press_enter
return 0 # Don't crash the script
fi
else
print_success "Step 1/5: cPanel Nginx already installed"
fi
# Step 2: Install Varnish
if ! check_varnish_installed; then
echo ""
print_info "Step 2/5: Installing Varnish..."
if ! install_varnish; then
print_error "Setup failed at Step 2"
press_enter
return 0 # Don't crash the script
fi
else
print_success "Step 2/5: Varnish already installed"
fi
# Step 3: Configure Varnish
echo ""
print_info "Step 3/5: Configuring Varnish..."
if ! configure_varnish_vcl; then
print_error "Setup failed at Step 3"
press_enter
return 1
fi
if ! configure_varnish_port "$recommended_mem"; then
print_error "Setup failed at Step 3"
press_enter
return 1
fi
# Step 4: Modify settings.json and configure Nginx to proxy to Varnish
# Apache stays on stock ea-nginx ports (81/444) - NO changes needed!
echo ""
print_info "Step 4/5: Configuring Nginx to proxy to Varnish..."
# First, modify settings.json to use Varnish port
if ! modify_settings_json; then
print_error "Setup failed at Step 4 (settings.json modification)"
press_enter
return 1
fi
# Then rebuild ea-nginx config from modified settings.json
if ! configure_nginx_varnish_proxy; then
print_error "Setup failed at Step 4 (nginx configuration)"
press_enter
return 1
fi
# Step 5: Start services
echo ""
print_info "Step 5/5: Starting services..."
systemctl enable varnish
systemctl restart varnish
if systemctl is-active --quiet varnish; then
print_success "Varnish started successfully"
if systemctl is-enabled --quiet varnish; then
print_success "Varnish enabled (auto-start on boot)"
fi
else
print_error "Failed to start Varnish"
press_enter
return 1
fi
systemctl restart nginx
if systemctl is-active --quiet nginx; then
print_success "Nginx restarted successfully"
else
print_error "Failed to restart Nginx"
press_enter
return 1
fi
# Create ea-nginx config-script as safety net
echo ""
print_info "Installing config-script for HTTPS→Varnish routing..."
create_eanginx_config_script
# Run config-script immediately to enable HTTPS caching
print_info "Applying HTTPS caching configuration..."
if bash /etc/nginx/ea-nginx/config-scripts/global/config-scripts-global-varnish 2>/dev/null; then
print_success "HTTPS traffic now routes through Varnish (HTTP protocol)"
else
print_warning "Config-script execution had issues - check logs"
fi
# Mark as configured
cat > "$STATUS_FILE" <<EOFSTATUS
CONFIGURED=yes
INSTALL_DATE=$(date +%Y-%m-%d)
VARNISH_MEMORY=${recommended_mem}m
BACKUP_PATH=$backup_path
EOFSTATUS
echo ""
print_success "═══════════════════════════════════════════════════════"
print_success "Setup completed successfully!"
print_success "═══════════════════════════════════════════════════════"
# Run diagnostics
echo ""
run_diagnostics
# Test domains
echo ""
print_info "Testing domain accessibility..."
echo ""
local test_domains=$(get_cpanel_domains | head -5)
if [ -n "$test_domains" ]; then
while IFS= read -r domain; do
test_domain "$domain" "http" || true
test_domain "$domain" "https" || true
done <<< "$test_domains"
else
print_warning "No domains found to test"
fi
echo ""
print_info "═══════════════════════════════════════════════════════"
print_info "Configuration Persistence:"
echo ""
print_success "✓ settings.json modified (apache_port = 6081)"
print_info " ea-nginx natively generates correct proxy config"
print_info " Preserved by RPM during package updates"
echo ""
print_success "✓ ea-nginx config-script installed (safety net)"
print_info " Auto-fixes if settings.json ever falls back to defaults"
print_info " Logs to: /var/log/nginx-varnish-hook.log"
echo ""
print_info "Backup: /etc/nginx/ea-nginx/settings.json.stock"
print_info "Backup location: $backup_path"
echo ""
print_warning "⚠ IMPORTANT NOTES:"
print_warning " • This setup is NOT officially supported by cPanel"
print_warning " • Config-script maintains configuration after ea-nginx updates"
print_success " ✓ Both HTTP and HTTPS traffic are cached by Varnish"
echo ""
print_info "To completely remove:"
print_info " • Use 'Revert Setup' to remove Nginx + Varnish"
print_info " • Returns server to stock Apache-only configuration"
echo ""
print_info "How HTTPS caching works:"
print_info " • SSL terminates at Nginx (standard practice)"
print_info " • Backend uses HTTP protocol to Varnish (config-script override)"
print_info " • Varnish caches all static content for both protocols"
echo ""
print_info "If using Cloudflare: This provides origin-level caching behind CDN"
print_info "═══════════════════════════════════════════════════════"
press_enter
}
################################################################################
# REVERT FUNCTION
################################################################################
revert_setup() {
print_banner "Revert Nginx + Varnish Setup"
# Check what's actually installed
local has_varnish_config=false
local has_nginx=false
local has_varnish=false
# Check Varnish configuration
if [ -f /etc/nginx/ea-nginx/settings.json ]; then
if grep -q '"apache_port" : "6081"' /etc/nginx/ea-nginx/settings.json 2>/dev/null; then
has_varnish_config=true
fi
fi
# Check if ea-nginx is installed
if check_nginx_installed; then
has_nginx=true
fi
# Check if Varnish is installed
if check_varnish_installed; then
has_varnish=true
fi
# If nothing to revert, exit
if [ "$has_nginx" = "false" ] && [ "$has_varnish" = "false" ] && [ "$has_varnish_config" = "false" ]; then
print_warning "Nothing to revert:"
print_info " • ea-nginx not installed"
print_info " • Varnish not installed"
print_info " • No Varnish configuration found"
echo ""
print_success "System is already in stock Apache-only configuration"
press_enter
return 0
fi
# Show what's currently installed
echo "Current state:"
if [ "$has_nginx" = "true" ]; then
echo " ✓ ea-nginx installed"
else
echo " ✗ ea-nginx not installed"
fi
if [ "$has_varnish" = "true" ]; then
echo " ✓ Varnish installed"
else
echo " ✗ Varnish not installed"
fi
if [ "$has_varnish_config" = "true" ]; then
echo " ✓ Varnish configuration active"
else
echo " ✗ Varnish configuration not active"
fi
echo ""
# Show appropriate revert options based on what's installed
echo "Available revert options:"
echo ""
local option_count=0
local partial_option=""
local full_option=""
# Option 1: Partial revert (only if Varnish exists)
if [ "$has_varnish" = "true" ] || [ "$has_varnish_config" = "true" ]; then
option_count=$((option_count + 1))
partial_option="1"
echo " 1) Partial Revert - Remove Varnish only (keep Nginx + Apache)"
echo " • Removes Varnish caching layer"
echo " • Keeps ea-nginx reverse proxy"
echo " • Result: Client → Nginx → Apache"
echo ""
fi
# Option 2: Full revert (if Nginx exists OR Varnish stuff needs cleanup)
if [ "$has_nginx" = "true" ] || [ "$has_varnish" = "true" ] || [ "$has_varnish_config" = "true" ]; then
option_count=$((option_count + 1))
if [ -z "$partial_option" ]; then
full_option="1"
echo " 1) Full Revert - Remove everything (return to stock Apache)"
else
full_option="2"
echo " 2) Full Revert - Remove everything (return to stock Apache)"
fi
if [ "$has_varnish" = "true" ]; then
echo " • Removes Varnish caching layer"
fi
if [ "$has_nginx" = "true" ]; then
echo " • Removes ea-nginx reverse proxy"
fi
if [ "$has_varnish_config" = "true" ]; then
echo " • Cleans up Varnish configuration"
fi
echo " • Result: Client → Apache (stock cPanel)"
echo ""
fi
echo " 0) Cancel"
echo ""
read -p "Select option: " revert_choice
case $revert_choice in
"$partial_option")
if [ -n "$partial_option" ]; then
revert_partial
else
print_error "Invalid option"
press_enter
return 1
fi
;;
"$full_option")
if [ -n "$full_option" ]; then
revert_full
else
print_error "Invalid option"
press_enter
return 1
fi
;;
0)
echo "Revert cancelled."
press_enter
return 0
;;
*)
print_error "Invalid option"
press_enter
return 1
;;
esac
}
revert_partial() {
print_banner "Partial Revert - Remove Varnish Only"
echo "This will:"
echo " 1. Stop and remove Varnish"
echo " 2. Configure Nginx to proxy directly to Apache"
echo " 3. Keep ea-nginx (Nginx reverse proxy)"
echo ""
print_info "Result: Client → Nginx → Apache (no caching)"
echo ""
read -p "Continue with partial revert? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Partial revert cancelled."
press_enter
return 0
fi
# Create backup before reverting
echo ""
print_info "Creating backup before revert..."
local backup_path=$(create_backup)
print_success "Backup created at: $backup_path"
# Stop Varnish
echo ""
print_info "Stopping Varnish..."
systemctl stop varnish || true
systemctl disable varnish || true
# Restore settings.json to stock
echo ""
restore_settings_json
# Rebuild ea-nginx config from restored settings.json
print_info "Rebuilding ea-nginx configuration..."
/usr/local/cpanel/scripts/ea-nginx config --global >/dev/null 2>&1 || true
print_success "Nginx now proxies directly to Apache (port 81)"
# Reload Nginx
print_info "Reloading Nginx..."
systemctl reload nginx
# Remove ea-nginx config script (safety net no longer needed)
echo ""
remove_eanginx_config_script
# Remove status file
rm -f "$STATUS_FILE"
echo ""
print_success "Varnish configuration reverted"
echo ""
# Remove Varnish package
print_info "Removing Varnish package..."
yum remove -y varnish >/dev/null 2>&1 || true
print_success "Varnish package removed"
echo ""
print_success "═══════════════════════════════════════════════════════"
print_success "Partial revert completed"
print_success "═══════════════════════════════════════════════════════"
echo ""
print_info "Your server configuration:"
print_info " • Nginx reverse proxy still active (ea-nginx)"
print_info " • Client → Nginx (80/443) → Apache (81/444)"
print_info " • No Varnish caching layer"
echo ""
print_info "Benefits you still have:"
print_info " • Nginx connection handling and buffering"
print_info " • Support for modern protocols (HTTP/2, etc.)"
echo ""
print_info "To fully remove Nginx and return to stock Apache:"
print_info " Run this revert option again and choose 'Full Revert'"
press_enter
}
revert_full() {
print_banner "Full Revert - Return to Stock Apache"
# Check what needs to be removed
local has_varnish=$(check_varnish_installed && echo "true" || echo "false")
local has_nginx=$(check_nginx_installed && echo "true" || echo "false")
local has_config=$([ -f /etc/nginx/ea-nginx/settings.json ] && grep -q '"apache_port" : "6081"' /etc/nginx/ea-nginx/settings.json 2>/dev/null && echo "true" || echo "false")
echo "This will remove:"
[ "$has_varnish" = "true" ] && echo " • Varnish package"
[ "$has_nginx" = "true" ] && echo " • ea-nginx package"
[ "$has_config" = "true" ] && echo " • Varnish configuration"
[ "$has_varnish" = "false" ] && [ "$has_nginx" = "false" ] && [ "$has_config" = "false" ] && echo " • Clean up any remaining configuration"
echo ""
echo "Result: Stock cPanel Apache-only configuration"
echo ""
print_warning "⚠ WARNING: This returns your server to stock Apache-only"
echo ""
read -p "Continue with full revert? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "Full revert cancelled."
press_enter
return 0
fi
# Create backup before reverting (if there's anything to backup)
if [ "$has_config" = "true" ]; then
echo ""
print_info "Creating backup before revert..."
local backup_path=$(create_backup)
print_success "Backup created at: $backup_path"
fi
# Stop Varnish (if running) (if running)
if systemctl is-active --quiet varnish 2>/dev/null; then
echo ""
print_info "Stopping Varnish..."
systemctl stop varnish || true
systemctl disable varnish || true
fi
# Restore settings.json to stock (if configured)
if [ -f /etc/nginx/ea-nginx/settings.json ]; then
if grep -q '"apache_port" : "6081"' /etc/nginx/ea-nginx/settings.json 2>/dev/null; then
echo ""
restore_settings_json
# Rebuild ea-nginx config from restored settings.json
print_info "Rebuilding ea-nginx configuration..."
/usr/local/cpanel/scripts/ea-nginx config --global >/dev/null 2>&1 || true
print_success "Configuration restored"
# Reload Nginx before removing it
if systemctl is-active --quiet nginx 2>/dev/null; then
print_info "Reloading Nginx..."
systemctl reload nginx
fi
fi
fi
# Remove ea-nginx config script (if exists)
if [ -f /etc/nginx/ea-nginx/config-scripts/global/config-scripts-global-varnish ]; then
echo ""
remove_eanginx_config_script
fi
# Remove status file (if exists)
if [ -f "$STATUS_FILE" ]; then
rm -f "$STATUS_FILE"
fi
echo ""
print_success "Varnish configuration cleaned up"
echo ""
# Remove Varnish package (if installed)
if check_varnish_installed; then
print_info "Removing Varnish package..."
yum remove -y varnish >/dev/null 2>&1 || true
print_success "Varnish package removed"
else
print_info "Varnish package already removed"
fi
# Remove ea-nginx and return to stock Apache
if check_nginx_installed; then
echo ""
print_info "Removing ea-nginx (Nginx reverse proxy)..."
print_warning " This will return your server to stock Apache-only configuration"
if /usr/local/cpanel/scripts/ea-nginx disable >/dev/null 2>&1; then
print_success "ea-nginx disabled"
fi
if yum remove -y ea-nginx >/dev/null 2>&1; then
print_success "ea-nginx package removed"
fi
else
echo ""
print_info "ea-nginx already removed"
fi
# Restart Apache to ensure it's listening on port 80/443
echo ""
print_info "Restarting Apache on stock ports..."
systemctl restart httpd
if systemctl is-active --quiet httpd; then
print_success "Apache is now running on ports 80/443 (stock configuration)"
fi
echo ""
print_success "═══════════════════════════════════════════════════════"
print_success "Full revert completed"
print_success "═══════════════════════════════════════════════════════"
echo ""
print_info "Your server has been returned to:"
print_info " • Stock cPanel Apache-only configuration"
print_info " • Apache listening directly on ports 80/443"
print_info " • No Nginx reverse proxy"
print_info " • No Varnish caching"
press_enter
}
################################################################################
# MEMORY ADJUSTMENT FUNCTIONS
################################################################################
adjust_varnish_memory() {
print_banner "Adjust Varnish Memory Allocation"
if ! check_varnish_installed; then
print_error "Varnish is not installed"
press_enter
return 0 # Don't crash the script
fi
local total_ram=$(get_total_ram_mb)
local current_mem=$(grep "ExecStart.*malloc" /etc/systemd/system/varnish.service.d/override.conf 2>/dev/null | grep -oP 'malloc,\K[0-9]+' || echo "unknown")
echo "Server total RAM: ${total_ram}MB"
echo "Current Varnish memory: ${current_mem}MB"
echo ""
echo "Select memory allocation:"
echo ""
echo " 1) 256MB - For servers with <2GB RAM"
echo " 2) 512MB - For servers with 2-4GB RAM"
echo " 3) 1GB - For servers with 4-8GB RAM"
echo " 4) 2GB - For servers with 8-16GB RAM"
echo " 5) 4GB - For servers with 16GB+ RAM"
echo " 6) Custom amount"
echo " 7) Auto-calculate based on current RAM usage"
echo " 0) Cancel"
echo ""
read -p "Select option: " mem_choice
local new_mem=""
case $mem_choice in
1) new_mem=256 ;;
2) new_mem=512 ;;
3) new_mem=1024 ;;
4) new_mem=2048 ;;
5) new_mem=4096 ;;
6)
echo ""
read -p "Enter custom memory in MB (or 0 to cancel): " custom_mem
if [ "$custom_mem" = "0" ] || [ -z "$custom_mem" ]; then
echo "Cancelled."
press_enter
return 0
fi
new_mem="$custom_mem"
;;
7)
new_mem=$(calculate_varnish_memory)
echo ""
print_info "Auto-calculated memory: ${new_mem}MB"
;;
0)
echo "Cancelled."
press_enter
return 0
;;
*)
print_error "Invalid option"
press_enter
return 1
;;
esac
if [ -z "$new_mem" ]; then
print_error "Invalid memory value"
press_enter
return 1
fi
echo ""
print_info "Setting Varnish memory to ${new_mem}MB..."
configure_varnish_port "$new_mem"
echo ""
print_info "Restarting Varnish..."
if systemctl restart varnish; then
print_success "Varnish memory updated to ${new_mem}MB"
# Update status file
if [ -f "$STATUS_FILE" ]; then
sed -i "s/VARNISH_MEMORY=.*/VARNISH_MEMORY=${new_mem}m/" "$STATUS_FILE"
fi
else
print_error "Failed to restart Varnish"
fi
press_enter
}
################################################################################
# CACHE MANAGEMENT FUNCTIONS
################################################################################
manage_varnish_cache() {
print_banner "Varnish Cache Management"
if ! systemctl is-active --quiet varnish; then
print_error "Varnish is not running"
press_enter
return 0 # Don't crash the script
fi
echo " 1) Clear all cache"
echo " 2) Clear cache for specific domain"
echo " 3) View cache statistics"
echo " 4) View cache hit ratio"
echo " 0) Cancel"
echo ""
read -p "Select option: " cache_choice
case $cache_choice in
1)
echo ""
print_info "Clearing all Varnish cache..."
if varnishadm "ban req.url ~ /" 2>/dev/null; then
print_success "Cache cleared successfully"
else
print_error "Failed to clear cache"
fi
;;
2)
echo ""
read -p "Enter domain name (or 0 to cancel): " domain
if [ "$domain" = "0" ] || [ -z "$domain" ]; then
echo "Cancelled."
else
print_info "Clearing cache for $domain..."
if varnishadm "ban req.http.host == $domain" 2>/dev/null; then
print_success "Cache cleared for $domain"
else
print_error "Failed to clear cache"
fi
fi
;;
3)
echo ""
print_info "Varnish cache statistics (press 'q' to quit):"
echo ""
varnishstat || print_error "Failed to get statistics"
;;
4)
echo ""
print_info "Cache hit ratio:"
echo ""
varnishstat -1 | grep -E 'cache_hit|cache_miss' || print_error "Failed to get statistics"
;;
0)
return 0
;;
*)
print_error "Invalid option"
;;
esac
press_enter
}
################################################################################
# BACKUP/RESTORE FUNCTIONS
################################################################################
manage_backups() {
print_banner "Backup & Restore Management"
echo " 1) Create new backup"
echo " 2) List available backups"
echo " 3) Restore from backup"
echo " 0) Cancel"
echo ""
read -p "Select option: " backup_choice
case $backup_choice in
1)
echo ""
print_info "Creating backup..."
local backup_path=$(create_backup)
print_success "Backup created at: $backup_path"
;;
2)
echo ""
if [ -d "$BACKUP_DIR" ] && [ "$(ls -A $BACKUP_DIR 2>/dev/null)" ]; then
echo "Available backups:"
echo ""
ls -lh "$BACKUP_DIR" | grep "^d" | awk '{print $9, "("$6, $7, $8")"}'
else
print_info "No backups found"
fi
;;
3)
echo ""
if [ ! -d "$BACKUP_DIR" ] || [ ! "$(ls -A $BACKUP_DIR 2>/dev/null)" ]; then
print_error "No backups available"
press_enter
return 0 # Don't crash the script
fi
echo "Available backups:"
echo ""
local backups=($(ls -d "$BACKUP_DIR"/backup_* 2>/dev/null | sort -r))
local count=1
for backup in "${backups[@]}"; do
echo " $count) $(basename "$backup")"
count=$((count + 1))
done
echo " 0) Cancel"
echo ""
read -p "Select backup to restore: " restore_choice
if [ "$restore_choice" = "0" ]; then
echo "Cancelled."
elif [ "$restore_choice" -ge 1 ] && [ "$restore_choice" -lt "$count" ]; then
local selected_backup="${backups[$((restore_choice - 1))]}"
echo ""
print_warning "This will restore configuration from: $(basename "$selected_backup")"
read -p "Continue? (yes/no): " confirm
if [ "$confirm" = "yes" ]; then
print_info "Restoring backup..."
# Check disk space before restore
local available_space=$(df /etc | tail -1 | awk '{print $4}')
if [ "$available_space" -lt 10240 ]; then
print_error "Insufficient disk space (less than 10MB available)"
press_enter
return 0 # Don't crash the script
fi
# Restore files
[ -f "$selected_backup/ea-nginx.conf" ] && cp -f "$selected_backup/ea-nginx.conf" /etc/nginx/
[ -d "$selected_backup/conf.d" ] && cp -rf "$selected_backup/conf.d/"* /etc/nginx/conf.d/
[ -f "$selected_backup/default.vcl" ] && cp -f "$selected_backup/default.vcl" /etc/varnish/
# Reload services
systemctl daemon-reload
systemctl reload nginx || true
systemctl restart varnish || true
print_success "Backup restored successfully"
else
echo "Restore cancelled."
fi
else
print_error "Invalid selection"
fi
;;
0)
return 0
;;
*)
print_error "Invalid option"
;;
esac
press_enter
}
################################################################################
# VIEW LOGS FUNCTION
################################################################################
view_logs() {
print_banner "View Service Logs"
echo " 1) Varnish logs (live)"
echo " 2) Nginx error log (tail)"
echo " 3) Nginx access log (tail)"
echo " 4) Apache error log (tail)"
echo " 0) Cancel"
echo ""
read -p "Select option: " log_choice
case $log_choice in
1)
echo ""
print_info "Viewing Varnish logs (press Ctrl+C to exit)..."
echo ""
varnishlog || print_error "Failed to view logs"
;;
2)
echo ""
print_info "Viewing Nginx error log (press Ctrl+C to exit)..."
echo ""
tail -f /var/log/nginx/error.log || print_error "Failed to view logs"
;;
3)
echo ""
print_info "Viewing Nginx access log (press Ctrl+C to exit)..."
echo ""
tail -f /var/log/nginx/access.log || print_error "Failed to view logs"
;;
4)
echo ""
print_info "Viewing Apache error log (press Ctrl+C to exit)..."
echo ""
tail -f /usr/local/apache/logs/error_log || print_error "Failed to view logs"
;;
0)
return 0
;;
*)
print_error "Invalid option"
;;
esac
press_enter
}
################################################################################
# MAIN MENU
################################################################################
show_varnish_menu() {
clear
print_banner "Nginx + Varnish Caching Manager"
# Detect current mode
local has_nginx=$(check_nginx_installed && echo "true" || echo "false")
local has_varnish=$(check_varnish_installed && echo "true" || echo "false")
local has_varnish_config=$([ -f /etc/nginx/ea-nginx/settings.json ] && grep -q '"apache_port" : "6081"' /etc/nginx/ea-nginx/settings.json 2>/dev/null && echo "true" || echo "false")
# Determine mode
local mode=""
local mode_color=""
if [ "$has_varnish" = "true" ] && [ "$has_nginx" = "true" ] && [ "$has_varnish_config" = "true" ]; then
mode="Varnish + Nginx + Apache (Full Stack)"
mode_color="${GREEN}"
elif [ "$has_nginx" = "true" ]; then
mode="Nginx + Apache (Reverse Proxy)"
mode_color="${YELLOW}"
else
mode="Apache Only (Stock cPanel)"
mode_color="${YELLOW}"
fi
echo -e "${mode_color}● Mode: ${mode}${NC}"
# Show installation info if configured
if [ "$has_varnish_config" = "true" ] && [ -f "$STATUS_FILE" ]; then
local install_date=$(grep "INSTALL_DATE" "$STATUS_FILE" | cut -d= -f2)
local varnish_mem=$(grep "VARNISH_MEMORY" "$STATUS_FILE" | cut -d= -f2)
echo " Installed: $install_date"
echo " Varnish Memory: $varnish_mem"
fi
# Always show port status with color coding
echo ""
echo " Services & Ports:"
# Check Nginx ports (80/443)
if ss -tlnp 2>/dev/null | grep -E ":80\s.*nginx" >/dev/null 2>&1 || netstat -tlnp 2>/dev/null | awk '$4 ~ /:80$/ && $7 ~ /nginx/' | grep -q .; then
echo -e " ${GREEN}${NC} Nginx: 80"
elif ss -tlnp 2>/dev/null | grep -E ":80\s.*httpd" >/dev/null 2>&1 || netstat -tlnp 2>/dev/null | awk '$4 ~ /:80$/ && $7 ~ /httpd/' | grep -q .; then
echo -e " ${GREEN}${NC} Apache: 80 (direct)"
else
echo -e " ${RED}${NC} Port 80 (not active)"
fi
if ss -tlnp 2>/dev/null | grep -E ":443\s.*nginx" >/dev/null 2>&1 || netstat -tlnp 2>/dev/null | awk '$4 ~ /:443$/ && $7 ~ /nginx/' | grep -q .; then
echo -e " ${GREEN}${NC} Nginx: 443"
elif ss -tlnp 2>/dev/null | grep -E ":443\s.*httpd" >/dev/null 2>&1 || netstat -tlnp 2>/dev/null | awk '$4 ~ /:443$/ && $7 ~ /httpd/' | grep -q .; then
echo -e " ${GREEN}${NC} Apache: 443 (direct)"
else
echo -e " ${RED}${NC} Port 443 (not active)"
fi
# Check Varnish port (6081)
if ss -tlnp 2>/dev/null | grep -E ":${VARNISH_PORT}\s.*varnish" >/dev/null 2>&1 || netstat -tlnp 2>/dev/null | awk -v port="$VARNISH_PORT" '$4 ~ ":"port"$" && $7 ~ /varnish/' | grep -q .; then
echo -e " ${GREEN}${NC} Varnish: ${VARNISH_PORT}"
else
echo -e " ${RED}${NC} Varnish: ${VARNISH_PORT}"
fi
# Check Apache backend ports (81/444)
if ss -tlnp 2>/dev/null | grep -E ":${APACHE_HTTP_PORT}\s.*httpd" >/dev/null 2>&1 || netstat -tlnp 2>/dev/null | awk -v port="$APACHE_HTTP_PORT" '$4 ~ ":"port"$" && $7 ~ /httpd/' | grep -q .; then
echo -e " ${GREEN}${NC} Apache: ${APACHE_HTTP_PORT}"
else
echo -e " ${RED}${NC} Apache: ${APACHE_HTTP_PORT}"
fi
if ss -tlnp 2>/dev/null | grep -E ":${APACHE_HTTPS_PORT}\s.*httpd" >/dev/null 2>&1 || netstat -tlnp 2>/dev/null | awk -v port="$APACHE_HTTPS_PORT" '$4 ~ ":"port"$" && $7 ~ /httpd/' | grep -q .; then
echo -e " ${GREEN}${NC} Apache: ${APACHE_HTTPS_PORT}"
else
echo -e " ${RED}${NC} Apache: ${APACHE_HTTPS_PORT}"
fi
echo ""
echo -e "${BOLD}Setup & Installation:${NC}"
echo ""
echo " 1) Full Setup - Install and configure complete stack"
echo " 2) Revert Setup - Remove Varnish integration"
echo ""
echo -e "${BOLD}Diagnostics & Maintenance:${NC}"
echo ""
echo " 3) Run Health Check - Diagnose configuration issues"
echo " 4) Auto-Fix Issues - Self-healing diagnostics"
echo " 5) Proof of Caching - Quick test showing MISS → HIT pattern"
echo ""
echo -e "${BOLD}Optimization:${NC}"
echo ""
echo " 6) Adjust Varnish Memory - Change RAM allocation"
echo " 7) Manage Varnish Cache - Clear cache, view stats"
echo ""
echo -e "${BOLD}Advanced:${NC}"
echo ""
echo " 8) Backup & Restore - Manage configuration backups"
echo " 9) View Logs - Service logs and monitoring"
echo ""
echo " 0) Return to Performance Menu"
echo ""
echo "═══════════════════════════════════════════════════════════"
echo -n "Select option: "
}
# Main loop
run_varnish_manager() {
while true; do
show_varnish_menu
read -r choice
case $choice in
1) full_setup ;;
2) revert_setup ;;
3) run_diagnostics; press_enter ;;
4) auto_fix_issues; press_enter ;;
5) proof_of_caching; press_enter ;;
6) adjust_varnish_memory ;;
7) manage_varnish_cache ;;
8) manage_backups ;;
9) view_logs ;;
0)
clear
exit 0
;;
*)
echo ""
print_error "Invalid option"
sleep 1
;;
esac
done
}
# Run main menu
run_varnish_manager