PHP-FPM (FastCGI Process Manager) is the recommended interface between Nginx and PHP on RHEL 8, replacing the older mod_php approach with a more flexible and performant process pool model. Rather than embedding PHP inside the web server, PHP-FPM runs as a separate systemd-managed service that Nginx communicates with over a Unix socket, isolating the two processes for better security and resource control. This tutorial walks through installing PHP-FPM from the RHEL 8 AppStream, tuning the pool configuration in /etc/php-fpm.d/www.conf, wiring it to Nginx via a Unix socket, and verifying the stack works end to end.

Prerequisites

  • RHEL 8 (or a compatible rebuild) with a valid subscription or configured repositories
  • Nginx installed (sudo dnf install nginx) and enabled
  • A user account with sudo privileges
  • No conflicting mod_php installation (Apache is not required and should not be running on the same port)

Step 1 — Install PHP-FPM via AppStream

The common profile of the PHP AppStream module includes php-fpm alongside php-cli and a standard extension set. If you have not yet installed PHP, run the following command. If PHP is already installed, dnf will detect that PHP-FPM is already present and skip it.

sudo dnf module install -y php:8.0/common
php-fpm --version

Confirm the version string matches your intended PHP release. The main PHP-FPM configuration file is /etc/php-fpm.conf and pool-specific configuration lives in /etc/php-fpm.d/.

Step 2 — Configure the PHP-FPM Pool

The default pool configuration file at /etc/php-fpm.d/www.conf controls how PHP-FPM listens for connections and manages worker processes. Edit it to use a Unix socket and to run under the nginx user and group so Nginx can connect to it.

sudo vi /etc/php-fpm.d/www.conf

Locate and update the following directives:

; Listen on a Unix socket instead of a TCP port
listen = /run/php-fpm/www.sock

; Owner and group of the socket file
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

; Run worker processes as the nginx user
user = nginx
group = nginx

; Process manager — dynamic is suitable for most production workloads
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

The dynamic process manager starts a fixed number of workers at boot and scales up and down within the configured limits based on demand. For a low-traffic server, reduce pm.max_children to conserve memory.

Step 3 — Enable and Start PHP-FPM

Enable PHP-FPM so it starts automatically on boot, then start it immediately and verify it is running.

sudo systemctl enable --now php-fpm
sudo systemctl status php-fpm
ls -la /run/php-fpm/www.sock

The ls command should show the socket file owned by nginx:nginx with mode srw-rw----. If the socket does not exist, check the PHP-FPM journal for errors:

sudo journalctl -u php-fpm --no-pager -n 30

Step 4 — Configure Nginx to Use the PHP-FPM Socket

Create or update an Nginx server block to pass .php requests to PHP-FPM over the Unix socket. The critical directives are fastcgi_pass, SCRIPT_FILENAME, and the fastcgi_params include.

sudo vi /etc/nginx/conf.d/default.conf
server {
    listen 80 default_server;
    server_name _;
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ .php$ {
        try_files $uri =404;
        fastcgi_pass unix:/run/php-fpm/www.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}
sudo nginx -t && sudo systemctl reload nginx

The try_files $uri =404 guard inside the PHP location block is a security measure that prevents Nginx from passing non-existent files to PHP-FPM, which can expose application internals.

Step 5 — Verify with a phpinfo Page

Create a temporary phpinfo.php test file in the web root, view it in a browser, and then remove it immediately. Leaving this file in place leaks sensitive server configuration to the public.

echo "<?php phpinfo();" | sudo tee /var/www/html/phpinfo.php
# Open http://your-server-ip/phpinfo.php in a browser, then:
sudo rm /var/www/html/phpinfo.php

The phpinfo output should show the PHP-FPM SAPI name as fpm-fcgi and display the pool configuration you set in www.conf. If the page is returned as plain text rather than rendered HTML, Nginx is not handing the request to PHP-FPM — recheck your fastcgi_pass directive and the socket path.

Step 6 — Apply SELinux Booleans

On RHEL 8 with SELinux in enforcing mode, you may need to enable specific booleans to allow PHP-FPM workers to connect to network services such as a database or send mail.

# Allow PHP-FPM to connect to remote databases
sudo setsebool -P httpd_can_network_connect_db 1

# Allow PHP-FPM to make arbitrary outbound network connections
sudo setsebool -P httpd_can_network_connect 1

# Verify active booleans
sudo getsebool -a | grep httpd_can

Only enable the booleans your application actually needs. Audit denials with sudo ausearch -m avc -ts recent if a feature stops working after deployment and SELinux is logging denials.

Conclusion

You have installed and configured PHP-FPM on RHEL 8 using the AppStream module, tuned the worker pool in /etc/php-fpm.d/www.conf, connected Nginx to PHP-FPM over a Unix socket, and verified the stack with a phpinfo test page. This configuration separates the web server and PHP runtime into distinct processes, improving both security and operational flexibility. You can now deploy PHP applications behind Nginx with confidence that the FastCGI layer is correctly set up.

Next steps: How to Install Laravel on RHEL 8, How to Install Symfony on RHEL 8, and How to Install PHP on RHEL 8.