When configuring Nginx with PHP-FPM, one of the most frustrating errors you might encounter is:
FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream
This typically manifests as a "File not found" error in the browser, even when the file clearly exists on your server.
The error occurs when Nginx can't properly communicate the script location to PHP-FPM. Common scenarios include:
- Incorrect
root
directive in Nginx configuration - Mismatched permissions between Nginx and PHP-FPM users
- Improper
fastcgi_param SCRIPT_FILENAME
setting - Path translation issues between Nginx and PHP-FPM
Here's a properly configured Nginx server block for PHP processing:
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 fastcgi_params; fastcgi_pass unix:/var/run/php/php5.6-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_intercept_errors on; } }
1. Verify file existence and permissions:
ls -la /var/www/example.com/public/index.php
2. Check Nginx and PHP-FPM user alignment:
ps aux | grep nginx ps aux | grep php-fpm
3. Test PHP-FPM connectivity:
SCRIPT_NAME=/test.php \ SCRIPT_FILENAME=/var/www/test.php \ QUERY_STRING= \ REQUEST_METHOD=GET \ cgi-fcgi -bind -connect /var/run/php/php5.6-fpm.sock
Case 1: The root
directive is set in server block but missing in location block.
Fix: Either move root to http context or duplicate it in location blocks.
Case 2: Using $request_filename
instead of $document_root$fastcgi_script_name
.
Fix: Stick to the standard pattern shown in the configuration above.
Case 3: PHP-FPM pool configuration has different chroot
or chdir
settings.
Fix: Check /etc/php/5.6/fpm/pool.d/www.conf
for conflicting directives.
For stubborn cases, enable detailed logging:
# In nginx.conf error_log /var/log/nginx/error.log debug; # In PHP-FPM pool config catch_workers_output = yes php_admin_value[error_log] = /var/log/fpm-php.www.log php_admin_flag[log_errors] = on
Then monitor both logs while reproducing the issue:
tail -f /var/log/nginx/error.log /var/log/fpm-php.www.log
While fixing this issue, be mindful of:
- Never set permissions to 777 - use proper user/group ownership
- Avoid using
alias
with PHP locations - Keep PHP-FPM pools isolated for different applications
- Regularly audit your
fastcgi_param
directives
When you see the error "Primary script unknown"
in your Nginx error logs while using PHP-FPM, it typically indicates a path resolution problem between Nginx and PHP-FPM. The web server cannot locate the PHP script you're trying to execute.
Here's a typical problematic Nginx configuration that could cause this:
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
The crucial missing piece here is the SCRIPT_FILENAME
parameter. Without it, PHP-FPM doesn't know which file to execute.
Here's the corrected version that should resolve the issue:
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;
}
Even with correct configuration, permission issues can cause the same error. Ensure:
- Nginx worker process has read permissions for PHP files
- PHP-FPM pool runs under a user with execute permissions
- Directory tree has proper traversal permissions (typically 755)
If your Nginx and PHP-FPM use different document roots, you'll need to explicitly set the path:
fastcgi_param SCRIPT_FILENAME /path/to/your/webroot$fastcgi_script_name;
To troubleshoot further:
- Check PHP-FPM logs:
/var/log/php5-fpm.log
- Verify file existence:
php -r "var_dump(file_exists('/path/to/script.php'));"
- Test FastCGI connectivity:
SCRIPT_FILENAME=/path/to/script.php REQUEST_METHOD=GET cgi-fcgi -bind -connect /var/run/php5-fpm.sock