"Curiosity is the very basis of education and if you tell me that curiosity killed the cat, I say only the cat died nobly." - Arnold Edinborough

“No input file specified” or “Primary script unknown” in the error log is one of the most frequently encountered issues in nginx+PHP. People on serverfault and in the #nginx IRC channel asks for help with this so often that this post is mostly to allow me to be lazy and not have to type up the same answer every time.

This is actually an error from PHP and due to display_errors being 0ff people will often just get a blank page with no output. In a typical setup PHP will then send the error to stderr or stdout and nginx will pick up on it and log it in the nginx error log file. Thus people spend a ton of time trying to figure out why nginx isn’t working.

The root cause of the error is that PHP cannot find the file nginx is telling it to look for, and there are a few common cases that causes this.

Wrong Path Sent to PHP

The most common reason at the time of writing happens because a user uses a horrible tutorial found via google instead of actually understanding nginx. Reading my nginx primer will equip you to actually solve this on your own but since this post is actually dedicated to the error I’ll cheat this once and allow you to be lazy by just giving you the full solution.

Nginx tells PHP about the file to execute via the SCRIPT_FILENAME fastcgi_param value. Most examples in the wiki should define this as $document_root$fastcgi_script_name. The horrible tutorials will often hard code the path value but this is not desirable as we don’t want to duplicate information and invite future screw ups. So you’ve gone with the $document_root$fastcgi_script_name option and suddenly it’s no longer working.

This happens because nginx has 3 levels of inheritance commonly referred to as blocks, these being http, server and location, each being a sub-block of the parent. Directives in nginx inherit downwards but never up or across, so if you define something in one location block it will never be applied in any other location block under any circumstance.

Typically users define their index and root directive in location / because a tutorial told them to. So when they then define SCRIPT_FILENAME using $document_root the root directive is not actually defined and thus the SCRIPT_FILENAME value becomes just the URI making PHP look at the root server dir.

The simple solution here is to just define the directive in your server block. (or http block even!) Generally the higher up your can define a directive the less duplicate directives you’ll need.

Incorrect File Permissions

Most people don’t really believe me when I tell them their file permissions are incorrect. They’re looking at the damn permissions and the PHP user can read the file just fine! Sadly, this shows a lack of understanding of Unix user permissions. Being able to read a file is not enough, a user must also be able to traverse to the file.

This effectively means that not only should the file have read permission, but the entire directory structure should have execute permission so that the PHP user can traverse the path. An example of this:

Say you have an index.php file in /var/www. /var/www/index.php must have read permission and both /var and /var/www must have execute permissions.

Using Alias and $document_root

It is fairly common to define SCRIPT_FILENAME as $document_root$fastcgi_script_filename; However, $document_root does not account for the alias directive and will thus result in an incorrect path being sent. It is preferable to define SCRIPT_FILENAME as such:

fastcgi_param SCRIPT_FILENAME $request_filename;

This accounts for alias and ensures proper path is sent. One note about this is that $request_filename does not account for fastcgi_index, but you only use this index if you send a request ending in / to PHP. If you use the standard PHP location ~ \.php$ then you will never use the fastcgi_index directive.

Chrooted Environment

If your PHP lives in a chrooted environment that nginx does not, then they basically have 2 different roots and the file path that nginx reports to PHP will not resolve to the actual file. A simple example to make this obvious:

Lets say you request phpinfo.php, nginx looks in your defined root and finds this file in: /home/user/public_html/phpinfo.php
The PHP process for user is chrooted to only have access to his directory for security reasons, so as far as PHP knows the root of the server is at /home/user. Therefore when nginx reports the file path PHP will look in: /home/user/home/user/public_html/phpinfo.php.

Either make sure both nginx and PHP has the same chroot or make sure you rewrite your internal URI before you fastcgi pass to PHP.

Open Basedir Restriction

PHP has the option to limit file access to certain directories defined in your php.ini. Some distributions might preconfigure this option for their packaging system.

SCRIPT_NAME Versus SCRIPT_FILENAME

Fastcgi has two parameters which are quite similiar in name, make sure that you’re not confusing the SCRIPT_NAME variable for the SCRIPT_FILENAME one. SCRIPT_FILENAME tells fastcgi the location of the script to execute while SCRIPT_NAME merely tells the name of the script.

  • str0x3r

    Posted: February 7, 2011


    Hey there!

    I think you were it who telled me to read this yesterday in nginx-irc.

    What i wan't to say is in first line thanks, i'm on the way to understand how nginx work.

    But there is one thing i really have to ask.

    Do you mean the root-directive should be put from location - block to the server - block?

    My english isn't as good in some specific "slangs", so i don't really know. Reply


    • fjordvald

      Posted: February 10, 2011


      Yeah you want your root directive in your server block as the $document_root variable is then available in all your location blocks. So if you pass to a backend and have to provide a path to the file to execute you can then use the $document_root variable and avoid duplicating your paths. Reply


  • Chen Yufei

    Posted: August 1, 2011


    Thanks! Clearly written about the problem and I solve it.

    I wish I'd read your Nginx Primer when I first come to nginx, so I don't need to waste my time on solving this problem.

    Anyway, I'm reading your Nginx Primer now :) Reply


  • Todd

    Posted: August 6, 2011


    Hi Martin

    Thanks for the explanation.

    May I ask you one question though? Why do people use SCRIPT_FILENAME = $document_root$fastcgi_script_name

    I've installed Nginx from a package, and this is a default FastCGI param:
    fastcgi_param SCRIPT_FILENAME $request_filename;

    Why would I change it to $document_root$fastcgi_script_name

    Many thanks Reply


    • fjordvald

      Posted: August 6, 2011


      $request_filename is actually just a shortcut for the document root (or alias) + the request URI. This means that so long as you do not rely on fastcgi_index then you can safely use $request_filename instead of $document_root$fastcgi_script_name.

      The important part is still that you keep root defined in server context so that it's available in your PHP location. Reply


  • Todd

    Posted: August 6, 2011


    Thanks for that reply Martin.

    One more question: do you think there's a lot of overlap between Nginx, Varnish and the W3 Total Cache WordPress plugin?

    For example, does the W3 page cache overlap with the Varnish cache? Intuitively, I imagine Varnish cache is quicker because (in my case - with malloc) it's using memory. I'd like to reduce overlap so am wondering if the perfect WordPress solution could do without a cache plugin, maybe just a minify plugin.

    Then there's browser caching, Gzip and headers. It seems you can set these from Nginx, Varnish or W3. I imagine a lot of installs out there are duplicating Gzip across Nginx and W3.

    I've looked through the nginx.conf that W3 produces and it's quite a mess. To keep things lightweight and simple, I'm thinking about ditching W3. Do you think there's anything really positive that W3 achieves, other than minify, that's not possible with Nginx or Varnish? Reply


    • fjordvald

      Posted: August 7, 2011


      There's a lot of overlap between Nginx and Varnish, so much that I don't even bother with Varnish at all, I just cache with Nginx. Application layer caching that is W3 Total Cache is completely unrelated, though, and I prefer using Memcached for that so it uses memory as well. As for Wordpress, it really does need a caching plugin, it's absolutely horrible without it. W3 with APC or Memcached storage engine is very clean and very easy to use and makes it so much faster. Reply


  • Henry

    Posted: December 11, 2011


    Thank you for your explanation!I know your means,But i still have some question.I have two work directory,one is D:\NET,one is E:\NET,i use alias or root in the location block,this two location have the same server block,so the server block have one root,when i vister the php files in D:\NET directory,i get a "No input file specified" error at then when i vister php files in E:NET directory,vice versa,In your means,because the root is in D:\NET,not E:\NET,how can i vister the php file at the same time at all of alias or root of location block? Reply


  • Adrian Ratnapala

    Posted: February 14, 2012


    Hi Martin,

    I am wondering if there are any other known causes of this error, because I am getting "No input file specified.", even though the paths and permissions seem fine. I am sorry to reward your excellent blogging by treating you like tech support, but I suspect that if I asked this on a PHP mailing list it might get ignored as an "nginx issue".

    Why do I think my config is fine? The "root" directive is in the server block; in fact if I use tcpdump to evesdrop on the fastcgi traffic, I see ....SCRIPT_NAME/var/www/index.php...", which looks fine too me. Similarly, the permissions are fine; I can become the same user as the PHP process and "cat" the source file.

    So it looks to me like it's an issue with PHP itself, but I can't prove it. Frustratingly, I have made all this work without any trouble at all on other machines!

    Cheers. Reply


  • Adrian Ratnapala

    Posted: February 14, 2012


    Hi. I just fixed the problem I mentioned abovfe! Mea Culpa I guess, but perhaps this is worth adding to your post: Debian's version of /etc/nginx/fastcgi_params defines SCRIPT_NAME but not SCRIPT_FILENAME. If I define the latter, things start to work.

    Is this a Debian bug? Or is it something else? Reply


    • fjordvald

      Posted: February 14, 2012


      It's not a bug really. fastcgi_params never included SCRIPT_FILENAME from the source, fastcgi.conf does, though. You could kind of consider fastcgi_params as deprecated. If anything it's a problem of the fastcgi protocol that it defines two variable names which are so close together that people will misread them as being one and the same. Reply


  • lotrix

    Posted: February 17, 2012


    my wordpress website does not seem to work with ur solution.. i have defined the complete root in the location block..

    I still get the error "No Input file specified " for this case

    http://lotrix.com/wp-admin

    but I dont get the same error for the below case

    http://lotrix.com/wp-admin/


    - just the forward slash is missing and nothing else.. what do you think might be the problem.... Reply


    • fjordvald

      Posted: February 19, 2012


      Can't help you unless you put a link to a pastebin of your config. Reply


  • jester

    Posted: February 23, 2012


    I tried to follow this closely, but am having several problems. I continue to get the "No input file specified" error for valid files, and on top of that, nothing is redirecting properly. I've fiddled endlessly, and looked for help on IRC, with no luck.

    Would be extremely grateful for a pointer. Relevant config and brief discussion is at

    http://paste.scsys.co.uk/183650

    Thank you. Reply


    • fjordvald

      Posted: February 24, 2012


      Your problem is that you have misunderstood the purpose of the root directory. The documentation here: http://wiki.nginx.org/HttpCoreModule#root states that the full URI is always appended to the root directory. So you end up looking in /usr/local/www/data/blog/blog. Fix your root and it should work. Reply


  • jester

    Posted: February 24, 2012


    Hmm. I had previously looked at that doc very closely, in another context, but I didn't really get it until now.

    But I'm afraid making this change still hasn't fixed it. I changed the root to /usr/local/www/data, and also tried changing location to "/blog/" (with closing slash), and I'm still getting 404's on bogus pages, and "No input file specified" for existing pages.

    Is there a way I can see exactly what file nginx is looking for? I tried changing the error_log to "info", but these things aren't showing up as errors in the logs.

    Thanks. Reply


  • lewy1

    Posted: April 12, 2012


    Thanks for the informative post. Unfortunately I still have the problem even though I believe everything mentioned in your post is set correctly. I posted the full details in the nginx forum here
    http://forum.nginx.org/read.php?15,225132
    but I didn't receive a reply. I'm pretty new to linux and assume it's a simple mistake but I have no idea what it is.
    Thanks Reply


    • mfjordvald

      Posted: April 13, 2012


      You'll want to check the permissions on /var as well, not just /var/www. If those are fine then next step is checking whether you're setting a chroot in php-fpm as that affects the path you should be sending to PHP. Reply


  • Peter M Dodge

    Posted: June 4, 2012


    Is there a way to redirect the "no input file specified" to a 404 page? This page is the only real relevant page turned up by google.

    The best I can think of is using httpd to serve up php which then can serve up error pages, but that eliminates the advantage of using nginx at all.

    Cheers,
    Peter M Dodge Reply


    • mfjordvald

      Posted: June 5, 2012


      Certainly, but not perfectly. If you check the headers for these requests you'll see that PHP is returning a 403 status header. This means that if you use fastcgi_intercept_errors along with error_page in your PHP passing location then you can handle the 403 errors fine.

      The problem is that you cannot tell the difference between no input file specified and 403s returned by your real application. If your nginx hosting server also have the PHP files then a simple try_files will be able to ever prevent the no input file specified error from even showing in the first place by just not passing a non-existent file to PHP. Reply


  • Jack

    Posted: November 21, 2012


    Thankyou so much,

    I couldn't find out what the issue was and this tutorial helped me understand unix and nginx so much better, that i worked out the problem myself (allowed directories in php.ini, something i would normally need to ask of a forum)

    Thankyou! Reply


  • dvd

    Posted: November 24, 2012


    So...
    I'm ashamed to say that your tuto saved my ass.
    I understood nginx and what I was doing in the config much better and solved my problem in 2 seconds (after searching the web for an hour).

    Thanks! Reply


  • Adam Colwell

    Posted: March 15, 2013


    I was having similar issues, and even tried all your steps.

    One extra thing to try which helped me was to check you have cgi.force_redirect = 0 set in php.ini

    Hope that helps! Reply


    • Martin Fjordvald

      Posted: March 15, 2013


      cgi.force_redirect is an Apache only feature, so yes it definitely needs to be disabled whenever you don't use mod_php. Reply


  • Dolmat

    Posted: July 24, 2013


    I cannot run info.php file in my webserver. I dont know what else to do. This is my sites-available/default
    http://pastebin.com/WDnqLwFy Reply


    • Martin Fjordvald

      Posted: July 24, 2013


      Nothing wrong with the config you pasted. Please check into your file permissions or provide more details. "cannot run info.php file in my web server" is not a useful error description. Reply


      • Dolmat

        Posted: July 24, 2013


        May i know which file permission?
        I just create a simple php file that show php info, but even that file cannot be viewed, it just show "No input file specified" Reply


        • Martin Fjordvald

          Posted: July 24, 2013


          It is specified in this very blog post how. If you don't know which permissions to set then please hire a server admin as that is beyond what I'm comfortable helping you with in a blog post. Reply


          • Dolmat

            Posted: July 24, 2013


            I changed the /usr/share/nginx/html permission to www-data, but still the same error appear


  • jack meow

    Posted: September 13, 2013


    Nice post!
    I really forgot about permission stuff. Reply


  • maria

    Posted: October 10, 2013


    I tried to follow your advice with my wordpress installation, but somehow without luck. The nginx-config is on http://pastebin.com/4yTMbvCz and the nginx-debug-level is on http://pastebin.com/8qUELibz. The file in the SCRIPT_FILENAME says:

    root@arm:/var/log/nginx# ll /usr/share/nginx/wordpress/wp-admin/install.php
    -rwxrwxrwx 1 www-data www-data 10447 Jun 30 13:18 /usr/share/nginx/wordpress/wp-admin/install.php*

    So I guess the permissions are proper resp. more then sufficient. Would you mind to give a helping hand? Reply


  • Nick S

    Posted: January 4, 2014


    Thanks for sharing those tips! I can't believe it, I had to spend a whole day trying to figure out why I was getting the "No file specified". Turned out that it was the latter - open_basdir restrictions. Commenting it out in the php.ini fixed the issue for me.

    Thanks again! Reply


  • alexus

    Posted: February 17, 2014


    root@test:~ # grep SCRIPT_FILENAME /usr/local/etc/nginx/nginx.conf | grep -v #
    fastcgi_param SCRIPT_FILENAME $request_filename;
    root@test:~ # grep ^open_basedir /usr/local/etc/php.ini
    root@test:~ # su -m www
    www@test:~ % file /usr/local/www/nginx/php/phpinfo.php
    /usr/local/www/nginx/php/phpinfo.php: PHP script, ASCII text
    www@test:~ %

    and yet still "No input file specified." Reply


    • Martin Fjordvald

      Posted: February 17, 2014


      Could you give a pastebin link to your config? Reply


      • alexus

        Posted: February 17, 2014


        sure, pastebin url is: http://pastebin.com/pz7eR53J Reply


        • Martin Fjordvald

          Posted: February 17, 2014


          Hi Alexus,

          You have the root defined in the location block which means it's not available in your PHP block. I cover this in my primer and in the Wrong Path Sent to PHP section. I see that you use $request_filename, however, this variable still uses the root or alias directive to construct the path so it should still be defined in server context - not location context. Reply


          • alexus

            Posted: February 18, 2014


            thank you for your reply, your blog's post was very interesting) i wish if i could nginx into some sort of debug mode where I can see what some of those variables are equivalent to, like $request_filename it'd probably help it solve a lot quicker.


  • alexus

    Posted: February 17, 2014


    turns out the problem was in "root" being specified in almost every "location" while it was only suppose to be defined once in "server" block. Reply


  • Sandip

    Posted: March 15, 2014


    Saved my time today ... thanks. SS Reply


  • Manel Monguilod

    Posted: October 22, 2014


    Thank you!!! Afeter looking for 2 hours I've found your web. Very clear explanation.

    P.D.: I'm guilty of a "copypasting" tutorials. That was my error :-) Reply



You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>