The error "FastCGI sent in stderr: Primary script unknown" typically occurs when Nginx cannot properly communicate with PHP-FPM to execute the requested script. This is fundamentally a path resolution problem between the web server and PHP processor.
Let's analyze the critical components in the configuration that need attention:
location ~ \\.php {
fastcgi_split_path_info ^(.+\\.php)(.*)$;
# Path resolution logic
set $fsn /$yii_bootstrap;
if (-f $document_root$fastcgi_script_name){
set $fsn $fastcgi_script_name;
}
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fsn;
}
Here are the most frequent causes and their solutions:
1. Incorrect Document Root
Verify both Nginx and PHP-FPM are using the same document root:
# In nginx.conf
root /var/www/project/public;
# In php-fpm pool config (www.conf)
chdir = /var/www/project/public
2. Permission Issues
Instead of using 777 permissions, implement proper ownership:
sudo chown -R www-data:www-data /var/www/project
sudo find /var/www/project -type d -exec chmod 755 {} \;
sudo find /var/www/project -type f -exec chmod 644 {} \;
3. PHP-FPM Configuration
Ensure your pool configuration matches:
[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
Here's a proven configuration that resolves the issue:
server {
listen 80;
server_name project.local;
root /var/www/project/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \\.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Follow this diagnostic sequence:
- Verify file exists:
ls -la /path/to/script.php
- Check Nginx error logs:
tail -f /var/log/nginx/error.log
- Confirm PHP-FPM is running:
sudo systemctl status php-fpm
- Test PHP-FPM directly:
SCRIPT_FILENAME=/path/to/script.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
For complex setups:
- When using Docker, ensure volume paths match between containers
- For symlinked deployments, set
realpath_root
in Nginx - With SELinux enabled, check context:
ls -Z /path/to/script.php
When migrating from Apache to Nginx, the "Primary script unknown" error often catches developers off guard. The error message in your logs indicates Nginx successfully passed the request to PHP-FPM, but the FastCGI processor couldn't locate the actual script file.
From your configuration, I notice several potential issues:
# Problematic original configuration
fastcgi_param SCRIPT_FILENAME $document_root$fsn;
# While $document_root points to /var/www/, $fsn may contain incorrect path
First, verify these critical elements:
# Correct PHP location block example
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Even with 777 permissions, SELinux might block access. Check:
ls -laZ /var/www/
ps aux | grep php-fpm
getenforce
Here's a proven configuration that works for PHP applications:
server {
listen 80;
server_name console.ordercloud;
root /var/www/console/frontend/www;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
When troubleshooting:
# Check PHP-FPM pool configuration
grep -R "listen" /etc/php/*/fpm/pool.d/
# Verify Nginx and PHP-FPM user permissions
ps aux | grep -E 'nginx|php-fpm'
Developers often miss:
- Mismatch between
fastcgi_pass
address and PHP-FPM listen address - Incorrect
SCRIPT_FILENAME
construction - Missing
try_files
directive in PHP location block - Path discrepancies between
root
directive and actual file location
Create a test PHP file:
echo "" > /var/www/console/frontend/www/test.php
Then access it via browser to confirm PHP processing works before debugging your application.