Deploy a PHP Website with Nginx on Ubuntu

A working Nginx server block for PHP-FPM, explained line by line — including the two mistakes that cause a raw PHP file to download instead of run.

By DevStudio Online Team · Published September 3, 2026

Unlike Apache, Nginx has no built-in PHP support — it hands .php requests off to PHP-FPM over a socket. Missing that handoff is the single most common reason a PHP site "downloads the file instead of running it."

Install PHP-FPM

sudo apt install php8.3-fpm
sudo systemctl enable --now php8.3-fpm

The server block

server {
    listen 80;
    server_name example.com;
    root /var/www/example.com/public;
    index index.php index.html;
 
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
 
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
 
    location ~ /\.ht {
        deny all;
    }
}

Line by line, the parts that actually matter:

  • try_files $uri $uri/ /index.php?$query_string; — this is what makes clean URLs work for frameworks with a front controller (Laravel, WordPress, etc.). Without it, only /index.php itself would load; every other route would 404.
  • fastcgi_pass unix:/run/php/php8.3-fpm.sock; — this is the actual handoff to PHP-FPM. Get the socket path wrong (or leave it pointing at a PHP version that isn't installed) and Nginx will serve the raw PHP source as a downloadable file instead of executing it, since Nginx itself doesn't know what to do with .php content on its own.
  • location ~ /\.ht — blocks any .htaccess/.htpasswd file from ever being served over HTTP (an Apache-era convention that Nginx ignores by default, but the files sometimes linger in a migrated codebase).

Enable the site

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t          # always test before reloading
sudo systemctl reload nginx

nginx -t catches a syntax error before it takes down your currently-running config — always run it before reload, not after something breaks.

If PHP files still download instead of running

Two things to check, in order:

  1. Confirm the socket path actually matches your installed PHP-FPM version: ls /run/php/ and make sure the filename in your config matches what's actually there.
  2. Confirm PHP-FPM is actually running: sudo systemctl status php8.3-fpm. A stopped FPM service produces the exact same "downloads instead of runs" symptom as a wrong socket path.
More Nginx guides