Nginx Returns 404 for PHP Files with PHP-FPM: Debugging and Solutions


3 views

When your Nginx setup returns 404 errors specifically for PHP files while serving static content perfectly, there's usually a configuration mismatch between Nginx and PHP-FPM. Let me walk through the critical checkpoints.

# Critical PHP handler configuration
location ~ \.php$ {
    fastcgi_pass   unix:/var/run/php/php7.4-fpm.sock; # Verify socket path
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    try_files      $uri =404; # Security measure
}

First verify your PHP-FPM connection method. For socket connections (most common):

fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

For TCP connections:

fastcgi_pass 127.0.0.1:9000;

Check these critical permission settings:

# Typical www-data setup
chown -R www-data:www-data /var/www/html
chmod -R 755 /var/www/html
find /var/www/html -type f -exec chmod 644 {} \;

Create a simple test.php with:

<?php
echo "PHP is working";
phpinfo();

Then check:

curl -I http://localhost/test.php

Always check error logs for precise diagnostics:

tail -f /var/log/nginx/error.log

Here's a verified working configuration:

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    
    index index.php index.html;
    
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    }
}

Verify your /etc/php/7.4/fpm/pool.d/www.conf contains:

listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
  • Mismatched socket paths between Nginx and PHP-FPM
  • Incorrect SCRIPT_FILENAME parameter
  • Missing index.php in index directive
  • Root directory path inconsistencies

When setting up Nginx with PHP-FPM, a common issue is receiving 404 errors specifically for PHP files while static files (HTML, CSS, JS) work perfectly. This suggests the problem lies in the PHP processing configuration rather than general file access permissions.

Here are the critical elements to verify in your Nginx configuration:

location ~ \\.php$ {
    # Absolute path is crucial here
    root /var/www/html;
    
    # Verify PHP-FPM socket path matches your actual setup
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    
    # This is the most important parameter for PHP execution
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    
    include fastcgi_params;
    try_files $uri =404;
}

1. Socket/Port Mismatch: Verify the PHP-FPM socket path matches what's configured in /etc/php-fpm.d/www.conf:

listen = /var/run/php-fpm/php-fpm.sock
; or
listen = 127.0.0.1:9000

2. SCRIPT_FILENAME Issues: The most common culprit. Try these alternatives:

# Option 1: Using $document_root
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

# Option 2: Hardcoded path (for testing)
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;

Here's a verified working configuration:

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    
    index index.php index.html;
    
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    location ~ \\.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

1. Check Nginx error logs: tail -f /var/log/nginx/error.log
2. Verify PHP-FPM is running: systemctl status php-fpm
3. Test PHP-FPM directly: SCRIPT_FILENAME=/var/www/html/test.php REQUEST_METHOD=GET cgi-fcgi -bind -connect unix:/var/run/php-fpm/php-fpm.sock

While 777 permissions are not recommended, ensure:
- Nginx worker user (usually nginx or www-data) has read access to files
- PHP-FPM pool user has execute permissions
- Directory permissions are at least 755