A PHP site can show a blank page, download PHP files, or return a 502 error when Nginx and PHP are not connected correctly. This Nginx PHP-FPM guide explains how the connection works, how to install the required packages on a supported Ubuntu release, and how to test the result safely in 2026.
You will build a simple Nginx virtual host, connect it to the installed PHP-FPM service, verify the FastCGI socket, and troubleshoot the problems that most often stop PHP applications from loading. The commands use Ubuntu’s package manager, so the exact PHP version may differ from one supported Ubuntu release to another.
What Nginx PHP-FPM does
Nginx is a web server. It handles browser connections, serves files such as HTML and images, and decides what should happen with each request. PHP-FPM is a separate service that runs PHP scripts for Nginx.
Think of Nginx as a receptionist and PHP-FPM as a specialist in a back office. Nginx receives a request for about.html and can serve it directly. When a visitor requests index.php, Nginx passes the script to PHP-FPM, receives the generated HTML, and sends that HTML back to the browser.
This separation is useful because each service has a focused job. Nginx is efficient at handling connections, while PHP-FPM manages PHP worker processes. The two services communicate through FastCGI, a protocol that passes a web request from Nginx to an application service.
Before you begin: choose a supported Ubuntu release
The original version of this article used Ubuntu 23.04. That release reached end of life on January 25, 2024, so it should not be used for a new public server. For a 2026 deployment, install a currently supported Ubuntu release and check its support status before you begin.
You can review the historical release notice in Ubuntu’s end-of-life notice and check the current support policy on the Ubuntu release cycle page. A supported release receives security maintenance and normally provides package names that work with the commands below.
You also need:
- A server running a supported Ubuntu release.
- An account with
sudoaccess. - A domain name pointing to the server, if you plan to use a public site.
- A document root, such as
/var/www/example.com/html. - A backup or a way to restore the server if you are changing an existing production configuration.
If the server already runs Apache, another web server, or a control panel, check which process owns ports 80 and 443 first. Two web servers cannot normally listen on the same port at the same time.
Update Ubuntu and install the web server
Start by refreshing the package list. Upgrading before installing services helps ensure that the system uses the latest packages available from the configured Ubuntu repositories.
sudo apt update
sudo apt upgrade -y
Now install Nginx. The package creates a system service and a default site configuration.
sudo apt install -y nginx
Start the service and configure it to start automatically after a reboot:
sudo systemctl enable --now nginx
sudo systemctl status nginx
On a server with a firewall, allow web traffic according to your security policy. If you use UFW, the Nginx profile names available on your system can be listed before enabling one:
sudo ufw app list
sudo ufw allow 'Nginx Full'
Only run the second command when UFW is already part of your firewall plan. Opening ports without understanding the existing rules can expose services you did not intend to publish.
Install PHP-FPM and useful PHP packages
Install PHP-FPM and the PHP extensions your application needs. Avoid copying a command that names an old PHP version, because supported Ubuntu releases can provide different versions.
sudo apt install -y php-fpm php-cli php-mysql php-curl php-gd php-mbstring php-xml php-zip php-opcache
These packages cover common needs such as command-line scripts, MySQL-compatible database connections, image handling, XML, compressed files, and bytecode caching. A particular application may require additional extensions, so check that application’s official requirements rather than installing every available module.
Confirm which PHP version and FPM service the package manager installed:
php -v
systemctl list-unit-files --type=service | grep -E 'php.*fpm'
ls -l /run/php/
The last command lists the available Unix sockets. A Unix socket is a local file that lets two services on the same server communicate. You may see a name such as /run/php/php8.3-fpm.sock or another version-specific path. Do not assume the socket is php8.1-fpm.sock; use the path that exists on your server.
Start the detected PHP-FPM service. Replace the service name in the example with the one returned by your system:
sudo systemctl enable --now php8.3-fpm
sudo systemctl status php8.3-fpm
If your service has a different version number, use that number in both commands. The service status should show that it is active. If it fails, inspect the journal before changing the Nginx configuration:
sudo journalctl -u php8.3-fpm --no-pager -n 50
Build an Nginx virtual host
An Nginx virtual host is a configuration block that tells the server how to handle one domain. This example uses example.com. Replace the domain and document-root path with your own values.
sudo mkdir -p /var/www/example.com/html
sudo chown -R "$USER":"$USER" /var/www/example.com/html
sudo nano /etc/nginx/sites-available/example.com
Add this configuration. The fastcgi_pass line must point to the PHP-FPM socket that exists on your server:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
The regular expression in the PHP location matches PHP file requests. The Ubuntu FastCGI snippet supplies common parameters, including the requested script filename. The final location blocks direct access to Apache .htaccess files, which should not be publicly readable.
Enable the site and remove the default site only if you no longer need it:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
Always run nginx -t before reloading. It checks the configuration syntax without interrupting the running service. A successful test normally reports that the syntax is okay and the test is successful.
Test the Nginx PHP-FPM connection safely
Testing a small PHP script confirms that Nginx can pass a request to PHP-FPM. Create a temporary file in the document root:
cat > /var/www/example.com/html/health.php <<'PHP'
<?php
echo 'PHP is running';
PHP
Open http://example.com/health.php in a browser or test it from the server with:
curl -i http://example.com/health.php
A response containing PHP is running shows that the request reached PHP-FPM and returned output. This is a better first test than exposing the complete PHP configuration, because a phpinfo() page can reveal environment details such as loaded modules, paths, and server variables.
If you temporarily create an information page while diagnosing a problem, remove it immediately after testing:
sudo rm /var/www/example.com/html/info.php
sudo rm /var/www/example.com/html/health.php
For example, if a developer leaves info.php online, anyone who can reach the URL may learn details that help target the server. A clean test file with one harmless response is usually enough for a basic connectivity check.
Common errors and how to fix them
502 Bad Gateway
A 502 error often means Nginx cannot reach PHP-FPM. Check that the service is running, then compare the socket in the Nginx configuration with the socket shown in /run/php/.
sudo systemctl status php8.3-fpm
ls -l /run/php/
sudo tail -n 50 /var/log/nginx/error.log
For example, if the directory contains php8.4-fpm.sock but the configuration uses php8.3-fpm.sock, update fastcgi_pass, run sudo nginx -t, and reload Nginx. The service name and socket version must match the installed package.
PHP downloads instead of running
If the browser downloads a PHP file, the request is probably being served as a static file. Check that the PHP location block exists, that it is inside the correct server block, and that Nginx was reloaded after the change.
Do not work around this by giving PHP files broad permissions or by moving them into a different directory. Fix the virtual host and confirm the configuration with sudo nginx -T, which prints the active Nginx configuration.
404 or the wrong website appears
A 404 response can mean that the requested file is not under the configured document root. Check the root path, the spelling of server_name, and the contents of the directory:
ls -la /var/www/example.com/html
sudo nginx -T | grep -E 'server_name|root|fastcgi_pass'
If the default Nginx page appears, the domain may not point to this server, the default site may still be enabled, or the request may not match the expected server name.
Permission denied
Nginx needs permission to read the document root and PHP-FPM needs permission to access the script. Keep files owned by an appropriate deployment account, use sensible directory permissions, and avoid making the entire web root writable by everyone.
When a framework needs a writable cache or upload directory, grant write access only to that specific directory. Making /var/www/example.com/html world-writable may hide the original problem and create a security risk.
Secure and maintain the server
Getting a test page to load is only the beginning. For a public site, use HTTPS, keep Ubuntu and application dependencies updated, and remove files that were created only for testing. A TLS certificate encrypts traffic between the visitor and the server; it does not replace updates or strong account security.
After the HTTP setup works, configure HTTPS with a certificate process appropriate for your environment. Then update the Nginx configuration carefully and test both HTTP and HTTPS behavior. If the site handles logins or payments, do not leave it on plain HTTP.
Review these routine tasks:
- Install security updates and review unattended-update behavior.
- Monitor Nginx and PHP-FPM logs for repeated errors.
- Back up site files, databases, and configuration files.
- Limit SSH access and use keys where practical.
- Remove unused PHP extensions and sample files.
- Check disk space so logs and uploads cannot fill the server.
One useful maintenance habit is to save a copy of the working virtual host configuration before making changes. If a later edit causes an outage, you can compare the files and restore the known-good version instead of guessing.
Nginx PHP-FPM setup checklist
Use this short checklist when setting up a new site or reviewing an existing one:
- Confirm that the Ubuntu release is supported for your 2026 deployment.
- Update packages and install Nginx.
- Install PHP-FPM and only the PHP extensions the application needs.
- Find the actual PHP-FPM service name and Unix socket.
- Create the document root and virtual host.
- Set
fastcgi_passto the existing socket path. - Run
sudo nginx -tbefore every reload. - Test a small PHP file, then delete it.
- Configure HTTPS and review permissions before publishing the site.
For example, a small personal site may need only Nginx, PHP-FPM, PHP-XML, and PHP-MBString. A store or content management system may also need a database extension, image support, and URL rewriting. Install based on the application’s requirements rather than copying a long package list from an unrelated server.
Frequently asked questions
What is the correct PHP-FPM socket for Ubuntu?
The correct socket is the one created by the PHP-FPM package installed on your server. Run ls -l /run/php/ and use the matching path in the Nginx fastcgi_pass directive.
Can I use Nginx PHP-FPM on Ubuntu 23.04?
You may encounter this setup on an old Ubuntu 23.04 server, but that release reached end of life on January 25, 2024. Do not use it for a new public deployment; migrate to a supported Ubuntu release and verify its package names and socket path.
Why does Nginx return a 502 error for PHP?
The usual causes are a stopped PHP-FPM service, a wrong socket path, or permissions that prevent communication. Check the PHP-FPM status, list /run/php/, and read the Nginx error log for the specific failure.
Should I leave phpinfo available on my website?
No. A public phpinfo() page can reveal useful server details. Use it only for a short test and delete it as soon as you finish troubleshooting.
Final takeaway
Nginx serves the request, PHP-FPM runs the PHP code, and the FastCGI socket connects the two. Most setup failures come from using an unsupported Ubuntu release, guessing the PHP version, or pointing Nginx at a socket that does not exist.
Your next step is to choose a supported Ubuntu release, install the packages, and verify the real service and socket names before editing the virtual host. For related PHP checks, see PHP INFO: How check PHP Version on a Site and keep TOP 30 MOST USEFUL COMMANDS IN LINUX available while you work.

