Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

My first time using Nginx, but I am more than familiar with Apache and Linux. I am using an existing project and when ever I am trying to see the index.php I get a 404 File not found.

Here is the access.log entry:

2013/06/19 16:23:23 [error] 2216#0: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client:, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://", host: "www.ordercloud.lh"

And here is the sites-available file:

server {
    set $host_path "/home/willem/git/console/www";
    access_log  /www/logs/console-access.log  main;

    server_name  console.ordercloud;
    root   $host_path/htdocs;
    set $yii_bootstrap "index.php";

    charset utf-8;

    location / {
        index  index.html $yii_bootstrap;
        try_files $uri $uri/ /$yii_bootstrap?$args;

    location ~ ^/(protected|framework|themes/\w+/views) {
        deny  all;

    #avoid processing of calls to unexisting static files by yii
    location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
        try_files $uri =404;

    # pass the PHP scripts to FastCGI server listening on
    location ~ \.php {
        fastcgi_split_path_info  ^(.+\.php)(.*)$;

        #let yii catch the calls to unexising PHP files
        set $fsn /$yii_bootstrap;
        if (-f $document_root$fastcgi_script_name){
            set $fsn $fastcgi_script_name;

        include fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fsn;

        #PATH_INFO and PATH_TRANSLATED can be omitted, but RFC 3875 specifies them for CGI
        fastcgi_param  PATH_INFO        $fastcgi_path_info;
        fastcgi_param  PATH_TRANSLATED  $document_root$fsn;

    location ~ /\.ht {
        deny  all;

My /home/willem/git/console is owned by www-data:www-data (my web user running php etc) and I have given it 777 permissions out of frustration...

My best guess is that something is wrong with the config, but I can't figure it out...

UPDATE So I moved it to /var/www/ and used a much more basic config:

server {
    #listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80 default ipv6only=on; ## listen for ipv6

    root /var/www/;
    index index.html index.htm;

    # Make site accessible from http://localhost/
    server_name console.ordercloud;

    location / {
        root           /var/www/console/frontend/www/;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /var/www;
            include        fastcgi_params;

    location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
            try_files $uri =404;

    location /doc/ {
        alias /usr/share/doc/;
        autoindex on;
        deny all;


Also if I call localhost/console/frontend/www/index.php I get a 500 PHP which means it is serving there. It just isn't serving off console.ordercloud ...

share|improve this question
Another possible cause: If you are using php-fpm, make sure the user set in /etc/php-fpm.d/www.conf has permissions for the script it is trying to run. I think it defaults to apache. – Dave Jul 8 '15 at 11:45

The error message “primary script unknown” is always related to a wrongly set SCRIPT_FILENAME in the nginx fastcgi_param directive.

You’re using an if in the configuration you posted first. Well it should be well known by now that if is evil and often produces problems.

Setting the root directive within a location block is bad practice, of course it works.

You could try something like the following:

server {
    location / {
        location ~* \.php$ {
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            try_files $uri @yii =404;
    location @yii {
        fastcgi_param SCRIPT_FILENAME $document_root$yii_bootstrap;

Please note that the above configuration is untested. You should execute nginx -t before applying it to check for problems that nginx can detect right away.

share|improve this answer
This solve it for me; I was not aware that you had to prefix $document_root, I assumed it did that automatically, based on root. – b01 Mar 14 '14 at 14:32
After upgrading system everything was broken, i found this answer and $document_root helped me too. Why my server worked properly before upgrade? – Nikita U. Mar 24 '15 at 22:33
Impossible to tell without the full configuration. – Fleshgrinder Mar 25 '15 at 20:00
Where can one learn more about the bad practice of setting the root within location? – Dan Dascalescu Jun 17 '15 at 9:20
For those who don't understand exactly how the variable might be wrong: add to main Nginx http section the following: log_format scripts '$document_root$fastcgi_script_name > $request'; (or whatever you're feeding to SCRIPT_FILENAME), and to your server: access_log /var/log/nginx/scripts.log scripts. Reload and take a look at your new scripts log ;) – igorsantos07 Aug 30 '15 at 22:53

Had the same problem with a newer nginx (v1.8). Newer versions recommend using snippets/fastcgi-php.conf; instead of fastcgi.conf. So if you copy/pasted include fastcgi.conf from a tutorial, you might end up with the Primary script unknown error in the log.

share|improve this answer

It's not always that the SCRIPT_FILENAME is wrong.
It may also be PHP is running as the wrong user/group.

This example is specific to Mac OS X, which in my experience is the most troublesome to setup (Debian is easy by comparison) - I've just upgraded from PHP 5.6 to 7.0, using homebrew and the excellent josegonzalez packages.

The problem was that a new copy of the config files was created.

The main config file is /usr/local/etc/php/7.0/php-fpm.conf, but note the Pool Definitions section at the end where it includes a whole subdirectory.


In php-fpm.d there's a www.conf file. By default this has:

user = _www
group = _www

On OS X, you may need to change this to:

user = [your username]
group = staff

(you should find this matches an ls -lh of your document_root)

Unfortunately without this change, you will still see this in your Nginx error log even if it's looking for the file in the correct place.

"Primary script unknown" while reading response header from upstream

Verify what it's currently running as:

ps aux | grep 'php-fpm'

or more cleanly:

ps aux | grep -v root | grep php-fpm | cut -d\  -f1 | sort | uniq

How to verify if the script filename is correct:

(stolen from igorsantos07 in the other answer)

Add to http block of main /usr/local/etc/nginx/nginx.conf:

log_format scripts '$document_root$fastcgi_script_name > $request';

(where the first bit needs to be whatever you're currently using, so you can see if it's right.)

And to use the log you've just defined, in your site's server block:

access_log /var/log/nginx/scripts.log scripts;

If it's correct, requesting will produce something like this:

/path/to/docroot/phpinfo.php > GET /phpinfo.php

Can you simplify your existing config?

Are you using a location ~ \.php { block you copied/pasted from somewhere off the internet? Most packages allow you to do it more quickly and cleanly. e.g. on OS X you now just need this:

location ~ \.php {
    include snippets/fastcgi-php.conf;

    # any site specific settings, e.g. environment variables

Things like fastcgi_split_path_info, try_files and fastcgi_index (defaults to index.php) are in /usr/local/etc/nginx/snippets/fastcgi-php.conf.

That in turn includes /usr/local/etc/nginx/fastcgi.conf which is a list of fastcgi_param settings, including the crucial SCRIPT_FILENAME.

Don't ever duplicate root in the PHP location block.

share|improve this answer
up vote 2 down vote accepted

Ok, so 3 things I found after a day of struggling

  1. For some reason I had already something running on port 9000 so I changed to 9001
  2. My default site was intercepting my new one, once again I don't under stand why since it shouldn't, but I just unlinked it
  3. Nginx doesn't automatically do the sym link for sites-available to site-enabled.

Hope this saves someone some trouble!

share|improve this answer
hello @we0, I have facing same issue with my setup. I have also running my another app on port 3001, so I have to host my php app on port 3002. you can see my original post here :… and… and another is…. Do you have any idea? – Manish Sapkal Nov 26 '15 at 6:28

I had this issue also, and I solved it by exchanging the lines include fastcgi_params and fastcgi_param SCRIPT_FILENAME ....

Indeed nginx sets the last value of each FastCGI parameter, so you have to put your value after the default value included in fastcgi_params.

share|improve this answer

Try to add root directive within your php location.

location ~ \.php {
      root /home/willem/git/console/www;
share|improve this answer
The root directive should be set on a per server basis and shouldn't be used within any location blocks (unless you're a pro and want to circumvent some very special nginx bugs in your configuration). – Fleshgrinder Oct 4 '14 at 17:42
@Fleshgrinder one root per server is not best practice. – Garet Claborn Oct 3 '15 at 2:58

I found the exact solution. It's because your php files doesn't have executing permission. Try chmod a=rwx yourphpfilesfolder -R that's it nothing else!

share|improve this answer
Nope, was what port I was listening on, look at the answer I posted as well – We0 Aug 12 '14 at 11:50
PHP files never need the execution bit because they are parsed and not executed. – Fleshgrinder Oct 4 '14 at 17:41

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.