How to Fix “No input file specified” in Nginx + PHP-FPM: Proper File Existence Checks and 404 Handling


2 views

When dealing with Nginx and PHP-FPM configurations, the infamous "No input file specified" error often stems from a fundamental gap in the request handling pipeline. The core issue occurs when:

  1. Nginx passes non-existent PHP file paths to PHP-FPM
  2. PHP-FPM attempts to execute missing files
  3. The error bypasses Nginx's normal 404 handling

Most tutorials suggest only setting SCRIPT_FILENAME, but this misses the crucial validation step:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

While necessary, this alone doesn't prevent PHP-FPM from receiving invalid paths.

Here's how to properly implement file existence checking in your Nginx config:

location ~ \.php$ {
    try_files $uri =404; # Critical security check
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    
    # Standard FastCGI params
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    
    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    fastcgi_index index.php;
}

1. try_files directive: Acts as a gatekeeper before requests reach PHP-FPM

2. Proper fastcgi_param ordering: Ensures SCRIPT_FILENAME is set before fastcgi_pass

3. Security implications: Prevents arbitrary code execution attempts

For more control, consider these additions:

location ~ \.php$ {
    try_files $uri =404;
    
    # Mitigate zero-day exploits
    fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/tmp/";
    
    # Timeout adjustments
    fastcgi_read_timeout 300;
    fastcgi_send_timeout 300;
    
    # Buffer optimizations
    fastcgi_buffer_size 128k;
    fastcgi_buffers 256 16k;
    
    # Standard configuration continues...
}

When troubleshooting, examine these log locations:

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

# PHP-FPM log
tail -f /var/log/php7.4-fpm.log

The try_files check adds minimal overhead since Nginx caches filesystem metadata. For high-traffic sites:

open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
  • Mismatched $document_root between Nginx and PHP-FPM
  • Incorrect filesystem permissions (PHP-FPM worker user needs read access)
  • Symbolic links breaking path resolution
  • Case sensitivity mismatches (common when migrating from Windows)

For those who prefer handling missing files at the PHP level:

location ~ \.php$ {
    try_files $uri @phpfallback;
    # ... standard config ...
}

location @phpfallback {
    return 404;
}

When dealing with Nginx and PHP-FPM configurations, the "No input file specified" error often persists even after setting fastcgi_param SCRIPT_FILENAME correctly. The root cause lies in how Nginx handles non-existent PHP files before passing requests to PHP-FPM.

Most tutorials suggest this basic configuration:

location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
}

The issue occurs when:

  • Nginx passes non-existent file paths to PHP-FPM
  • PHP-FPM returns the raw error instead of allowing Nginx to handle 404s
  • The error appears in logs as Unable to open primary script: ... (No such file or directory)

Here's the proper way to implement a file existence check before passing to PHP-FPM:

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

For enhanced security and proper error handling:

location ~ ^(.+\.php)(.*)$ {
    try_files $fastcgi_script_name =404;
    
    set $path_info $fastcgi_path_info;
    fastcgi_param PATH_INFO $path_info;
    
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}

Combine with these Nginx directives for proper error management:

fastcgi_intercept_errors on;
error_page 404 /custom_404.html;
  • Check Nginx error logs: tail -f /var/log/nginx/error.log
  • Verify PHP-FPM socket permissions
  • Test with simple scripts to isolate the issue