WHM only applies PHP-FPM settings to new accounts, and as we know, the cPanel defaults may not be appropriate for higher-traffic sites. This script updates all existing accounts.
#!/bin/bash
# bulk-phpfpm-tuner.sh
# Updates PHP-FPM pool settings for all accounts based on server RAM
TOTAL_RAM_MB=$(free -m | awk '/^Mem:/{print $2}')
RESERVED_MB=2048 # Reserve for OS/MySQL
ACCOUNTS=$(whmapi1 listaccts | grep -oP '(?<=user: )\w+')
ACCOUNT_COUNT=$(echo "$ACCOUNTS" | wc -l)
# Calculate per-account max_children
AVAILABLE_RAM=$((TOTAL_RAM_MB - RESERVED_MB))
AVG_PHP_PROCESS_MB=50
MAX_CHILDREN_TOTAL=$((AVAILABLE_RAM / AVG_PHP_PROCESS_MB))
MAX_CHILDREN_PER_ACCOUNT=$((MAX_CHILDREN_TOTAL / ACCOUNT_COUNT))
# Minimum of 5, maximum of 50 per account
[[ $MAX_CHILDREN_PER_ACCOUNT -lt 5 ]] && MAX_CHILDREN_PER_ACCOUNT=5
[[ $MAX_CHILDREN_PER_ACCOUNT -gt 50 ]] && MAX_CHILDREN_PER_ACCOUNT=50
echo "Server RAM: ${TOTAL_RAM_MB}MB | Accounts: $ACCOUNT_COUNT | max_children per account: $MAX_CHILDREN_PER_ACCOUNT"
for user in $ACCOUNTS; do
for domain_file in /var/cpanel/userdata/$user/*.php-fpm.yaml; do
[[ -f "$domain_file" ]] || continue
# Update or create the yaml settings
if grep -q "pm_max_children" "$domain_file"; then
sed -i "s/pm_max_children:.*/pm_max_children: $MAX_CHILDREN_PER_ACCOUNT/" "$domain_file"
else
echo "pm_max_children: $MAX_CHILDREN_PER_ACCOUNT" >> "$domain_file"
fi
if grep -q "pm_process_idle_timeout" "$domain_file"; then
sed -i "s/pm_process_idle_timeout:.*/pm_process_idle_timeout: 10s/" "$domain_file"
else
echo "pm_process_idle_timeout: 10s" >> "$domain_file"
fi
done
echo "Updated: $user"
done
# Rebuild PHP-FPM configs
/scripts/php_fpm_config --rebuild
echo "Done. Restart PHP-FPM services to apply."