Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Linux & Mac & Bash Command Dictionary

  1. Home
  2. Linux & Mac & Bash Command Dictionary
  3. Nginx + PHP-FPM

Nginx + PHP-FPM

"Nginx + PHP-FPM" is a configuration that runs PHP applications by combining Nginx, a high-performance web server, with PHP FastCGI Process Manager (PHP-FPM). Nginx handles static file delivery, and PHP script execution is delegated to PHP-FPM processes via the fastcgi_pass directive. This approach uses memory more efficiently than Apache + mod_php and provides stable performance even under high traffic.

Syntax

# -----------------------------------------------
#  Installing PHP-FPM (Ubuntu / Debian)
# -----------------------------------------------

# Install the php8.3-fpm package
#   → Both the PHP-FPM daemon and the CLI are installed together
#   Example: sudo apt install php8.3-fpm
sudo apt install php8.3-fpm

# -----------------------------------------------
#  Installing PHP-FPM (RHEL / AlmaLinux)
# -----------------------------------------------

# Install the php-fpm package
#   Example: sudo dnf install php php-fpm
sudo dnf install php php-fpm

# -----------------------------------------------
#  Starting PHP-FPM and enabling auto-start
# -----------------------------------------------

# Start the PHP-FPM service
#   Example: sudo systemctl start php8.3-fpm
sudo systemctl start php8.3-fpm

# Enable PHP-FPM to start automatically at boot
sudo systemctl enable php8.3-fpm

# Check the current service status
sudo systemctl status php8.3-fpm

# -----------------------------------------------
#  Nginx fastcgi_pass configuration (Unix socket)
# -----------------------------------------------

# Create a virtual host config file in /etc/nginx/sites-available/
# Forward PHP file requests to PHP-FPM via fastcgi_pass

server {
    listen 80;
    server_name nerv.example.com;
    root /var/www/nerv;
    index index.php index.html;

    # Forward PHP file requests to PHP-FPM
    location ~ \.php$ {
        # Connect to PHP-FPM via a Unix socket
        #   → Lower overhead than a TCP port; recommended when both run on the same server
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;

        # Specify the default index file passed to PHP-FPM
        fastcgi_index index.php;

        # Pass the actual file path of the script to PHP-FPM
        #   → Combine $document_root and $fastcgi_script_name
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        # Load the standard parameters defined in fastcgi_params
        #   → Sets environment variables such as QUERY_STRING and REQUEST_METHOD
        include fastcgi_params;
    }

    # Block direct access to .htaccess files
    location ~ /\.ht {
        deny all;
    }
}

# -----------------------------------------------
#  Nginx fastcgi_pass configuration (TCP port)
# -----------------------------------------------

# Use this when PHP-FPM runs on a separate server,
# or when www.conf is configured with listen = 127.0.0.1:9000

server {
    listen 80;
    server_name nerv.example.com;
    root /var/www/nerv;
    index index.php index.html;

    location ~ \.php$ {
        # Connect to PHP-FPM via TCP port 9000
        fastcgi_pass 127.0.0.1:9000;

        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

# -----------------------------------------------
#  PHP-FPM pool configuration (/etc/php/8.3/fpm/pool.d/www.conf)
# -----------------------------------------------

# Specify the pool name (default is www)
[www]

# Set the user and group that PHP-FPM worker processes run as
#   → Matching Nginx's worker_processes user prevents permission issues
user = www-data
group = www-data

# Specify the connection type (Unix socket or TCP port)
#   → Unix socket (recommended): listen = /run/php/php8.3-fpm.sock
#   → TCP port: listen = 127.0.0.1:9000
listen = /run/php/php8.3-fpm.sock

# Specify the process management mode
#   → dynamic: automatically adjusts the number of processes based on load (recommended)
#   → static: always keeps pm.max_children processes running
#   → ondemand: terminates idle processes to save memory
pm = dynamic

# Set the maximum number of processes that can run simultaneously
#   → Adjust based on available server memory
#   → Guideline: available memory (MB) / memory per process (MB)
pm.max_children = 10

# Set the number of processes to start when PHP-FPM launches
pm.start_servers = 3

# Set the minimum number of idle processes to keep alive
pm.min_spare_servers = 2

# Set the maximum number of idle processes to keep alive
pm.max_spare_servers = 5

Syntax reference

SettingDescription
fastcgi_passSpecifies the connection target for PHP-FPM. You can specify a Unix socket (unix:/run/php/php8.3-fpm.sock) or a TCP port (127.0.0.1:9000). A Unix socket is recommended when both services run on the same server.
fastcgi_indexSpecifies the default filename to append when the URI ends with a slash. Typically set to index.php.
fastcgi_param SCRIPT_FILENAMEPasses the absolute path of the script for PHP-FPM to execute. The standard value is $document_root$fastcgi_script_name. If this is missing, PHP-FPM cannot find the file and returns an error.
include fastcgi_paramsLoads the standard FastCGI parameters defined in /etc/nginx/fastcgi_params all at once, including QUERY_STRING, REQUEST_METHOD, SERVER_NAME, and others.
listen in www.confSpecifies how PHP-FPM listens for connections. Set to a Unix socket path or in IP:port format. This value must match the fastcgi_pass directive in Nginx.
pm in www.confSpecifies the process management mode. Choose from dynamic (automatically adjusts based on load), static (fixed count), or ondemand (terminates idle processes). dynamic is recommended for general use.
pm.max_children in www.confSets the maximum number of PHP-FPM processes that can run simultaneously. Use the server's total memory divided by the estimated memory per process (roughly 30–50 MB) as a starting point.
pm.start_servers in www.confSpecifies how many processes to start when the PHP-FPM service launches. Set to a value between pm.min_spare_servers and pm.max_spare_servers.
pm.min_spare_servers in www.confSpecifies the minimum number of idle processes to keep running at all times. Keeping a certain number ready ensures fast responses when traffic spikes.
pm.max_spare_servers in www.confSpecifies the maximum number of idle processes to maintain. Any idle processes beyond this limit are automatically terminated to free memory.
user / group in www.confSpecifies the user and group that PHP-FPM worker processes run as. Matching this with Nginx's worker user (typically www-data) prevents file permission issues.

Examples

/etc/nginx/sites-available/nerv-php.conf
# -----------------------------------------------
#  Nginx virtual host config for the NERV PHP site
# -----------------------------------------------

server {
    listen 80;

    # Specify the server name (multiple names allowed)
    server_name nerv.example.com www.nerv.example.com;

    # Set the document root
    root /var/www/nerv;

    # Specify the priority order of index files
    index index.php index.html index.htm;

    # Root location block
    #   → try_files checks for a file, then a directory, then returns 404
    location / {
        try_files $uri $uri/ =404;
    }

    # Forward PHP file requests to PHP-FPM
    location ~ \.php$ {
        # Path injection protection: verify the file actually exists
        try_files $uri =404;

        # Enable FastCGI split path info
        fastcgi_split_path_info ^(.+\.php)(/.+)$;

        # Connect to PHP-FPM via a Unix socket
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;

        fastcgi_index index.php;

        # Pass the full path of the script for PHP-FPM to execute
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        # Load standard FastCGI parameters
        include fastcgi_params;

        # Set a 60-second timeout (for slow or heavy requests)
        fastcgi_read_timeout 60;
    }

    # Block access to hidden files such as .htaccess
    location ~ /\.ht {
        deny all;
    }

    # Set access and error log paths
    access_log /var/log/nginx/nerv_access.log;
    error_log /var/log/nginx/nerv_error.log;
}

Run the following command:

$ sudo apt update
$ sudo apt install nginx php8.3-fpm
$ sudo systemctl start nginx
$ sudo systemctl start php8.3-fpm
$ sudo systemctl enable nginx
$ sudo systemctl enable php8.3-fpm
$ sudo ln -s /etc/nginx/sites-available/nerv-php.conf /etc/nginx/sites-enabled/
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo systemctl reload nginx
$ sudo mkdir -p /var/www/nerv
$ sudo chown -R www-data:www-data /var/www/nerv
$ sudo nano /var/www/nerv/info.php
(After creating info.php, open http://nerv.example.com/info.php in your browser to verify the setup)
/var/www/nerv/info.php
<?php
// -----------------------------------------------
//  Verification file for PHP-FPM + Nginx
//  Use this to confirm the PHP environment is working
// -----------------------------------------------

// Calling phpinfo() displays PHP version, configuration,
// and loaded extension modules in the browser.
// Delete this file after verification for security reasons.
phpinfo();
?>

Run the following command:

(Open http://nerv.example.com/info.php in your browser)
(If "PHP Version 8.3.x" is displayed and Server API shows "FPM/FastCGI", Nginx + PHP-FPM is working correctly)

$ curl -s http://nerv.example.com/info.php | grep -i "server api"
<tr><td class="e">Server API </td><td class="v">FPM/FastCGI </td></tr>

(Once verified, delete info.php)
$ sudo rm /var/www/nerv/info.php
/etc/php/8.3/fpm/pool.d/www.conf
# -----------------------------------------------
#  PHP-FPM pool configuration (tuned for the NERV server)
# -----------------------------------------------

[www]

# Run PHP-FPM worker processes as www-data
#   → Match this with Nginx's worker user
user = www-data
group = www-data

# Listen for connections on a Unix socket
#   → Must match fastcgi_pass in Nginx
listen = /run/php/php8.3-fpm.sock

# Set the socket owner and group so Nginx can read and write it
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

# Automatically adjust process count based on load
pm = dynamic

# Maximum number of processes that can run simultaneously
#   → Guideline for 1 GB RAM: 1024 / 40 ≒ 25
pm.max_children = 20

# Number of processes to start at launch
pm.start_servers = 5

# Minimum number of idle processes to keep alive
pm.min_spare_servers = 3

# Maximum number of idle processes to keep alive
pm.max_spare_servers = 8

# Slow log: record requests that take longer than 5 seconds
slowlog = /var/log/php8.3-fpm-slow.log
request_slowlog_timeout = 5s

Run the following command:

$ sudo php-fpm8.3 -t
[25-Mar-2026 09:00:00] NOTICE: configuration file /etc/php/8.3/fpm/php-fpm.conf test is successful
$ sudo systemctl restart php8.3-fpm
$ sudo systemctl status php8.3-fpm
● php8.3-fpm.service - The PHP 8.3 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.3-fpm.service; enabled)
     Active: active (running) since Wed 2026-03-25 09:00:05 JST
   Main PID: 12345 (php-fpm8.3)
     Status: "Processes active: 0, idle: 5, Requests: 0, slow: 0, Traffic: 0req/sec"

Overview

"Nginx + PHP-FPM" is an architecture in which Nginx handles fast delivery of static content while PHP execution is offloaded to separate PHP-FPM processes, enabling efficient and scalable PHP serving. PHP-FPM manages a process pool and, with the pm = dynamic setting, automatically adjusts the number of running processes based on traffic. There are two ways to connect Nginx to PHP-FPM: Unix sockets (recommended when both run on the same server) and TCP ports. The socket approach has lower latency than TCP because communication stays within the kernel. Use systemctl to start, stop, and enable services. In production, configure a firewall with ufw or iptables to close unnecessary ports. After verifying the setup, be sure to delete debug files such as info.php.

If you find any errors or copyright issues, please .