Nginx and PHP-FPM together create a high-performance stack for serving dynamic PHP content. Nginx handles static files and request routing efficiently, while PHP-FPM (FastCGI Process Manager) manages PHP script execution through a separate process pool. This separation allows each component to be optimized independently, making the combination ideal for hosting WordPress sites, Laravel applications, or any PHP-based web project.
This guide walks through configuring Nginx to communicate with PHP-FPM on Fedora. You will adjust the PHP-FPM pool settings to run under the correct user, verify the socket permissions, create a working server block, and test the complete integration. By the end, your server will be ready to process PHP requests.
Prerequisites
Before configuring the integration, you need both Nginx and PHP-FPM installed on your system. If you have not installed them yet, follow these guides first:
Once both packages are installed, verify they are available on your system:
nginx -v
php-fpm -v
Expected output confirming both are installed:
nginx version: nginx/1.x.x PHP 8.x.x (fpm-fcgi) (built: ...) Copyright (c) The PHP Group Zend Engine v4.x.x, Copyright (c) Zend Technologies
Understand the Default Configuration
Fedora ships with pre-configured integration files that simplify the Nginx and PHP-FPM connection. Before making changes, it helps to understand what exists by default so you can avoid unnecessary modifications.
PHP-FPM Pool Configuration
The main PHP-FPM pool configuration file is located at /etc/php-fpm.d/www.conf. Check the current user and group settings:
grep -E '^(user|group)' /etc/php-fpm.d/www.conf
Default output on a fresh installation:
user = apache group = apache
By default, PHP-FPM runs as the apache user because the package was historically designed for Apache HTTP Server. However, since Nginx runs as the nginx user, you need to change these settings to ensure proper file permissions and ownership.
Socket Permissions
PHP-FPM communicates with Nginx through a Unix socket. Check the socket configuration:
grep -E '^listen' /etc/php-fpm.d/www.conf
Expected output:
listen = /run/php-fpm/www.sock listen.acl_users = apache,nginx listen.allowed_clients = 127.0.0.1
Fedora already includes nginx in the listen.acl_users directive, which grants Nginx permission to connect to the PHP-FPM socket. This means you do not need to modify socket ownership or permissions.
Pre-configured Nginx Integration Files
Additionally, Fedora provides ready-to-use configuration files for Nginx and PHP-FPM integration. First, check the upstream definition file:
cat /etc/nginx/conf.d/php-fpm.conf
Expected output showing the upstream definition:
# PHP-FPM FastCGI server
# network or unix domain socket configuration
upstream php-fpm {
server unix:/run/php-fpm/www.sock;
}
This file defines a named upstream called php-fpm that points to the Unix socket. Next, examine the default PHP handler configuration:
cat /etc/nginx/default.d/php.conf
Expected output showing the location block for PHP files:
# pass the PHP scripts to FastCGI server
#
# See conf.d/php-fpm.conf for socket configuration
#
index index.php index.html index.htm;
location ~ \.(php|phar)(/.*)?$ {
fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;
fastcgi_intercept_errors on;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php-fpm;
}
These pre-configured files mean the default Nginx server block already supports PHP. As a result, the only required change is updating the PHP-FPM user and group settings.
Configure PHP-FPM for Nginx
Open the PHP-FPM pool configuration file in your preferred text editor:
sudo nano /etc/php-fpm.d/www.conf
Locate the user and group directives near the top of the file (around lines 24-26) and change them from apache to nginx:
Before:
user = apache group = apache
After:
user = nginx group = nginx
Save the file and exit the editor. If using nano, press Ctrl+O to save, then Ctrl+X to exit.
Changing the user and group ensures PHP-FPM worker processes run with the same permissions as Nginx. This prevents ownership conflicts when PHP scripts create or modify files in your web directories.
Alternatively, use sed to make these changes without opening an editor:
sudo sed -i 's/^user = apache/user = nginx/' /etc/php-fpm.d/www.conf
sudo sed -i 's/^group = apache/group = nginx/' /etc/php-fpm.d/www.conf
Verify the changes took effect:
grep -E '^(user|group)' /etc/php-fpm.d/www.conf
Expected output confirming the new settings:
user = nginx group = nginx
Enable and Start Services
With the configuration changes complete, enable both services to start automatically at boot and start them now:
sudo systemctl enable --now nginx php-fpm
If the services were already running, restart them to apply the configuration changes:
sudo systemctl restart nginx php-fpm
Verify both services are running:
systemctl status nginx php-fpm --no-pager
Expected output showing both services active:
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
Active: active (running) since ...; Xs ago
Main PID: XXXX (nginx)
Tasks: 3 (limit: 4652)
Memory: 5.2M
CPU: 25ms
CGroup: /system.slice/nginx.service
├─XXXX "nginx: master process /usr/sbin/nginx"
└─XXXX "nginx: worker process"
● php-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; preset: disabled)
Active: active (running) since ...; Xs ago
Main PID: XXXX (php-fpm)
Status: "Processes active: 0, idle: 5, Requests: 0, slow: 0, Traffic: 0req/sec"
Tasks: 6 (limit: 4652)
Memory: 12.5M
CPU: 45ms
CGroup: /system.slice/php-fpm.service
├─XXXX "php-fpm: master process (/etc/php-fpm.conf)"
└─XXXX "php-fpm: pool www"
Test the PHP Integration
To confirm the configuration is valid, test the Nginx syntax:
sudo nginx -t
Expected output confirming the configuration is correct:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Next, create a PHP info file to verify the complete stack is working. This file displays PHP configuration details and confirms Nginx is correctly passing requests to PHP-FPM:
echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/html/info.php
Test the file from the command line using curl:
curl -s http://localhost/info.php | head -20
Expected output showing PHP information (HTML formatted):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<style type="text/css">
body {background-color: #fff; color: #222; font-family: sans-serif;}
...
<title>PHP 8.x.x - phpinfo()</title>
If you see HTML output containing PHP version information, the integration is working correctly. You can also open http://your-server-ip/info.php in a web browser to see the full PHP info page.
Security note: Remove the info.php file after testing. The
phpinfo()output exposes sensitive server configuration details that attackers could exploit.
sudo rm /usr/share/nginx/html/info.php
Configure Firewall Rules
If you are running firewalld (Fedora’s default firewall), you need to allow HTTP and HTTPS traffic. First, check if firewalld is active:
sudo firewall-cmd --state
If the firewall is running, add the HTTP and HTTPS services:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Verify the rules were added:
sudo firewall-cmd --list-services
Expected output showing HTTP and HTTPS in the list:
cockpit dhcpv6-client http https ssh
SELinux Considerations
Fedora has SELinux enabled and enforcing by default, which provides an additional layer of security. In most cases, the default SELinux policies allow Nginx and PHP-FPM to work correctly. However, if your PHP application needs to perform certain actions like connecting to databases or sending emails, you may encounter permission denials.
Check if SELinux is blocking anything. If the ausearch command is not found, install the audit package first with sudo dnf install audit:
sudo ausearch -m avc -ts recent 2>/dev/null | grep -E 'nginx|php-fpm' | tail -5
If you see AVC denial messages related to Nginx or PHP-FPM, common solutions include:
Allow Nginx to connect to backend services (databases, external APIs):
sudo setsebool -P httpd_can_network_connect 1
Allow PHP to send emails:
sudo setsebool -P httpd_can_sendmail 1
Allow PHP to connect to databases:
sudo setsebool -P httpd_can_network_connect_db 1
Only enable the SELinux booleans your application actually requires. Each enabled boolean slightly reduces the security boundary that SELinux provides.
Create a Custom Server Block
While the default Nginx configuration works for testing, production sites typically use custom server blocks with their own document roots. The following example demonstrates a complete server block for hosting a PHP site:
sudo nano /etc/nginx/conf.d/example.conf
Add the following configuration, replacing example.com with your domain:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.php index.html index.htm;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass php-fpm;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
This configuration includes:
- try_files in root location: Enables clean URLs for frameworks like WordPress and Laravel
- try_files $uri =404 in PHP location: Returns 404 for non-existent PHP files instead of passing them to PHP-FPM
- Deny .ht files: Blocks access to .htaccess and other Apache configuration files that may exist
Create the document root directory and set proper ownership:
sudo mkdir -p /var/www/example.com/html
sudo chown -R nginx:nginx /var/www/example.com
Set the correct SELinux context for web content. If the semanage command is not found, install it first with sudo dnf install policycoreutils-python-utils:
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/example.com(/.*)?"
sudo restorecon -Rv /var/www/example.com
Test the configuration and reload Nginx:
sudo nginx -t && sudo systemctl reload nginx
Troubleshooting Common Issues
502 Bad Gateway Error
This error typically means Nginx cannot connect to PHP-FPM. Check if PHP-FPM is running:
systemctl status php-fpm
If PHP-FPM is running, verify the socket exists and has correct permissions:
ls -la /run/php-fpm/www.sock
Expected output:
srw-rw----+ 1 root root 0 ... /run/php-fpm/www.sock
The + at the end indicates ACL permissions are set. To verify nginx is in the ACL, use getfacl (install with sudo dnf install acl if needed):
getfacl /run/php-fpm/www.sock
File Not Found or Blank Page
If PHP files return 404 or blank pages, check:
- Document root: Verify the
rootdirective in your server block points to the correct directory - File ownership: Ensure files are owned by the nginx user:
ls -la /var/www/yoursite/ - PHP-FPM error log: Check for errors in
/var/log/php-fpm/www-error.log - Nginx error log: Check
/var/log/nginx/error.logfor request processing errors
Permission Denied Errors
If you see “Permission denied” in logs, SELinux may be blocking access. Check the audit log:
sudo ausearch -m avc -ts recent | tail -20
If denials appear, you can generate a policy to allow the specific action. The audit2allow command is part of the policycoreutils-python-utils package mentioned earlier:
sudo ausearch -m avc -ts recent | audit2allow -M mypolicy
sudo semodule -i mypolicy.pp
Conclusion
With PHP-FPM configured to run as the nginx user and the pre-configured integration files in place, your Fedora server can now process PHP requests through Nginx. The default configuration covers most use cases, while custom server blocks allow you to host multiple PHP sites with their own document roots and settings. For production environments, consider adding SSL certificates with Let’s Encrypt, enabling gzip compression for better performance, and configuring security headers to protect your PHP applications. If you plan to deploy containerized PHP applications, explore our guide on installing Docker on Fedora.