Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

1. Overview

When working with an unconfigured Nginx web server to host a PHP application, we commonly notice that the server prompts us to download PHP files instead of executing them. This happens because Nginx isn’t configured to handle PHP requests by default.

In this tutorial, we’ll learn how to configure Nginx to execute PHP files properly instead of downloading them, ensuring our server runs PHP applications smoothly.

2. Understanding the Issue

PHP is a separate program from Nginx that lacks out-of-the-box integration with Nginx or other popular web servers like Apache. To resolve download issues with PHP files, we first install PHP-FPM (FastCGI Process Manager) and configure it with Nginx, allowing Nginx to pass PHP files to PHP-FPM for processing.

If we don’t do this, Nginx treats PHP files as static files (such as HTML or CSS) and sends them to the client instead of executing them server-side.

3. Prerequisites

Before moving forward, let’s ensure that Nginx is installed on the system:

$ nginx -v
nginx version: nginx/1.24.0

Next, let’s install PHP-FPM on a Debian or Ubuntu-based distribution:

$ sudo apt install php-fpm

Now, we’re ready to configure Nginx with PHP-FPM to serve PHP files.

4. Configuring Nginx to Execute PHP Files

Even though PHP-FPM has been installed, we still need to configure Nginx with the following steps:

4.1. Modify Nginx Server Block

First, let’s navigate to the Nginx configuration file, typically located at /etc/nginx/sites-available/ with a default filename. However, depending on the setup, separate virtual host files might be present, and in that case, we edit those files as required.

Afterward, let’s locate the server block within the file where we should enable PHP processing. In a typical server block, it looks like this:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    
    root /var/www/html;
    index index.html index.htm;

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

    # other configurations
}

To enable PHP execution, we simply add a new location block to handle .php files within the server block.

4.2. Add PHP Handling Location Block

Let’s assume the Nginx configuration file with the default filename is the one we want to edit, so let’s open it using nano:

$ sudo nano /etc/nginx/sites-available/default

Next, let’s modify the server block and add index.php to the index line to specify the order in which Nginx serves the index files:

server {
...
    root   html;
    index  index.php index.html index.htm;
...
}

Finally, let’s ensure the .php files pass to the PHP-FPM backend by adding the given location block:

...
location ~* \.php$ {
    fastcgi_index   index.php;
    fastcgi_pass    unix:/var/run/php/php-fpm.sock;
    include         fastcgi_params;
    fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
}
...

Let’s break down the critical parts of this configuration:

  • location ~* \.php$ matches all requests with PHP files where ~* is a regular expression that tells Nginx to match all PHP files in a case-insensitive manner
  • fastcgi_index index.php sets index.php as the default PHP file for directory requests (e.g., /example/ serves /example/index.php if it exists)
  • fastcgi_pass forwards all PHP requests to PHP-FPM via a Unix socket. In this case, it uses a Unix socket /var/run/php/php-fpm.sock to communicate with PHP-FPM
  • include fastcgi_params includes necessary FastCGI parameters, such as HTTP headers, server information, and environment variables
  • fastcgi_param SCRIPT_FILENAME defines the full file path to the PHP script that Nginx passes to PHP-FPM for processing. It combines $document_root (the root directory of the server) and $fastcgi_script_name (the requested PHP file) to construct the complete path
  • fastcgi_param SCRIPT_NAME sets the SCRIPT_NAME variable, which holds the path of the requested PHP file (e.g., the URL path without the domain), which PHP-FPM uses to handle the request

After modifying the file, the final configuration should look like the following:

...
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    
    root /var/www/html;
    index   index.php index.html index.htm;

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

    location ~* \.php$ {
        fastcgi_index   index.php;
        fastcgi_pass    unix:/var/run/php/php-fpm.sock;
        include         fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
    }
}
...

Let’s ensure to save the changes and close the file.

4.3. Testing the Configuration

Let’s test the changes to confirm they are correct:

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Next, let’s restart the Nginx server to apply the changes:

$ sudo systemctl restart nginx

Afterward, let’s create an index.php file with the given content in the document root:

<?php
phpinfo();
?>

Finally, let’s navigate to http://localhost in the browser, where we see the output of the phpinfo() function, confirming that PHP executes correctly through Nginx.

5. Conclusion

In this article, we configured Nginx to handle PHP files properly by installing PHP-FPM and adjusting the Nginx configuration, establishing a seamless integration between the web server and the PHP processor.

We also learned about essential Nginx configurations, such as modifying the server block and adding the necessary location directives, ensuring that PHP files route to PHP-FPM for execution. After verifying our configuration and restarting the server, we validated our setup with a simple test, confirming that our PHP environment is now fully operational.