Learn how to enable and configure PHP slow logs on CloudPanel with NGINX to identify performance bottlenecks, optimize PHP-FPM scripts, and improve your server’s response time.

How to enable the slowlog for all the websites hosted in CloudPanel

When troubleshooting performance issues in PHP applications, one of the most valuable yet often overlooked tools is the PHP slow log. This feature enables developers and system administrators to identify scripts or functions that take too long to execute, helping to uncover bottlenecks, inefficient queries, or poorly optimized code. If your server runs NGINX under CloudPanel, enabling the PHP slow log can provide deep insights into what’s causing slow responses or high resource usage. CloudPanel, with its clean interface and NGINX-based architecture, provides a powerful environment for managing PHP sites; however, performance optimization still requires visibility into what happens behind the scenes.

In this article, we’ll walk through the steps to enable and configure the PHP slow log on a CloudPanel-managed NGINX server. You’ll learn where to find the configuration files, how to adjust logging thresholds, and how to interpret the output to fine-tune your PHP performance.

1. Create the script to enable PHP slow logs in NGINX (CloudPanel)

To make this process as easy as possible, I wrote a script for you that is compatible with any FPM setup. This Bash script enables and standardizes PHP-FPM slow-request logging across all custom pool configuration files on a server. It’s written defensively with set -euo pipefail, so it stops on errors, treats undefined variables as failures, and propagates pipeline errors. At the top, it defines a few knobs:

  1. The PHP version to target (defaulting to 5.6)
  2. The pool configuration directory
  3. A dedicated slow-log directory
  4. A slow-request threshold (default 5s)
  5. A DRY_RUN flag that lets you preview changes without modifying anything (DRY_RUN=1 ./setup-php-slowlog.sh).

Create the script:

nano setup-php-slowlog.sh

And paste the following content inside:

#!/usr/bin/env bash
set -euo pipefail

# ===== SETTINGS =====
PHP_VER="5.6"
POOL_DIR="/etc/php/${PHP_VER}/fpm/pool.d"
LOG_DIR="/var/log/php${PHP_VER}-fpm-slow"
TIMEOUT="5s"                 # e.g. 2s, 5s, 10s
DRY_RUN="${DRY_RUN:-0}"      # DRY_RUN=1 ./setup-php-slowlog.sh

# ===== PREP =====
if [[ ! -d "$POOL_DIR" ]]; then
  echo "ERROR: Pool dir not found: $POOL_DIR" >&2
  exit 1
fi
[[ "$DRY_RUN" == "0" ]] && mkdir -p "$LOG_DIR"

# Collect pool files (exclude www.conf and default.conf)
mapfile -t CONF_FILES < <(find "$POOL_DIR" -maxdepth 1 -type f -name '*.conf' \
  ! -name 'www.conf' ! -name 'default.conf' | sort)

echo "=== Debug: Found $((${#CONF_FILES[@]})) pool conf(s) in $POOL_DIR ==="
printf ' - %s\n' "${CONF_FILES[@]}"
echo "=============================================================="
echo

apply_conf_changes() {
  local conf="$1"                                  # full path
  local domain
  domain="$(basename "$conf" .conf)"               # without .conf
  local slowlog_path="${LOG_DIR}/${domain}-slow.log"

  # Read pool user/group (fallbacks)
  local user group
  user="$(awk -F'=' '/^[[:space:]]*user[[:space:]]*=/{gsub(/[[:space:]]/,"",$2); print $2}' "$conf" | tail -n1 || true)"
  group="$(awk -F'=' '/^[[:space:]]*group[[:space:]]*=/{gsub(/[[:space:]]/,"",$2); print $2}' "$conf" | tail -n1 || true)"
  [[ -z "$user" ]] && user="www-data"
  [[ -z "$group" ]] && group="$user"

  echo "→ $domain  (user=$user group=$group)"
  echo "   conf:    $conf"
  echo "   slowlog: $slowlog_path"

  if [[ "$DRY_RUN" == "0" ]]; then
    cp -a "$conf" "${conf}.bak-$(date +%F_%H%M%S)"

    # request_slowlog_timeout (set or update)
    if grep -Eq '^[[:space:]]*;?[[:space:]]*request_slowlog_timeout[[:space:]]*=' "$conf"; then
      sed -ri "s|^[[:space:]]*;?[[:space:]]*request_slowlog_timeout[[:space:]]*=.*$|request_slowlog_timeout = ${TIMEOUT}|" "$conf"
    else
      printf "\n; added by enable-fpm-slowlog\nrequest_slowlog_timeout = %s\n" "$TIMEOUT" >> "$conf"
    fi

    # slowlog (set or update)
    if grep -Eq '^[[:space:]]*;?[[:space:]]*slowlog[[:space:]]*=' "$conf"; then
      sed -ri "s|^[[:space:]]*;?[[:space:]]*slowlog[[:space:]]*=.*$|slowlog = ${slowlog_path}|" "$conf"
    else
      printf "slowlog = %s\n" "$slowlog_path" >> "$conf"
    fi

    # ensure file exists & perms
    touch "$slowlog_path"
    chown "${user}:${group}" "$slowlog_path"
    chmod 0640 "$slowlog_path"
  fi

  echo
}

# ===== MAIN =====
if [[ ${#CONF_FILES[@]} -eq 0 ]]; then
  echo "No .conf files (excluding www.conf and default.conf) were found in $POOL_DIR"
  exit 0
fi

for conf in "${CONF_FILES[@]}"; do
  echo "Processing raw file: '$conf'"
  apply_conf_changes "$conf"
done

echo "Validating php-fpm config..."
if [[ "$DRY_RUN" == "0" ]]; then
  if command -v php-fpm5.6 >/dev/null 2>&1; then
    php-fpm5.6 -t
  elif command -v php5.6-fpm >/dev/null 2>&1; then
    php5.6-fpm -t
  elif command -v php-fpm >/dev/null 2>&1; then
    php-fpm -t
  else
    echo "php-fpm test command not found; continuing."
  fi

  echo "Reloading php-fpm service..."
  if systemctl list-units --type=service | grep -q '^php5\.6-fpm\.service'; then
    systemctl reload php5.6-fpm || systemctl restart php5.6-fpm
  elif systemctl list-units --type=service | grep -q '^php-fpm\.service'; then
    systemctl reload php-fpm || systemctl restart php-fpm
  else
    service php5.6-fpm reload || service php5.6-fpm restart || true
  fi
fi

echo "Done. Tail logs with: tail -f ${LOG_DIR}/*-slow.log"

2. Running the script

Once you’ve saved the script (for example, as setup-php-slowlog.sh) and made it executable with:

chmod +x setup-php-slowlog.sh

you can run it directly from your terminal. The script must be executed with root or sudo privileges because it modifies PHP-FPM configuration files and log directories under /etc and /var/log.

To apply the changes immediately:

sudo ./setup-php-slowlog.sh

This will back up each pool configuration, inject the request_slowlog_timeout and slowlog directives, validate the PHP-FPM configuration, and reload the service automatically. If you want to preview what the script will do without actually changing anything, use dry-run mode:

DRY_RUN=1 ./setup-php-slowlog.sh

You’ll see exactly which files would be modified, what log paths would be created, and which pool users and groups would be used, without touching the filesystem. At this point, slow requests in any configured pool will automatically be logged to their corresponding slow log files.

If you run the script without the DRY RUN mode, you will get an output similar to the following (depending on how many websites you're running on the cloudpanel server):

=== Debug: Found 1 pool conf(s) in /etc/php/5.6/fpm/pool.d ===
 - /etc/php/5.6/fpm/pool.d/ourcodeworld.com.conf
==============================================================

Processing raw file: '/etc/php/5.6/fpm/pool.d/ourcodeworld.com.conf'
→ ourcodeworld.com  (user=ourcodeworld group=ourcodeworld)
   conf:    /etc/php/5.6/fpm/pool.d/ourcodeworld.com.conf
   slowlog: /var/log/php5.6-fpm-slow/ourcodeworld.com-slow.log

Validating php-fpm config...
[13-Oct-2025 16:40:59] NOTICE: configuration file /etc/php/5.6/fpm/php-fpm.conf test is successful

Reloading php-fpm service...
Done. Tail logs with: tail -f /var/log/php5.6-fpm-slow/*-slow.log

By enabling and monitoring the PHP slow log in NGINX under CloudPanel, you gain a powerful window into your application’s performance. With this insight, you can pinpoint inefficient scripts, optimize resource usage, and ensure your PHP stack runs at peak efficiency — keeping your server fast, stable, and ready for growth.

Happy coding ❤️!


Senior Software Engineer at Software Medico. Interested in programming since he was 14 years old, Carlos is a self-taught programmer and founder and author of most of the articles at Our Code World.

Sponsors