“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.
- Previous Post
- Words by: Martin Fjordvald
- January 19, 2011
- 51 Comments
- Next Post
-
-
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 :)
-
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
-
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?
-
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?
-
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.
-
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?
-
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....
-
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.
-
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.
-
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
-
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
-
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!
-
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!
-
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!
-
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
-
jack meow
Posted: September 13, 2013
Nice post!
I really forgot about permission stuff.
-
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:
[email protected]:/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?
-
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!
-
alexus
Posted: February 17, 2014
[email protected]:~ # grep SCRIPT_FILENAME /usr/local/etc/nginx/nginx.conf | grep -v #
fastcgi_param SCRIPT_FILENAME $request_filename;
[email protected]:~ # grep ^open_basedir /usr/local/etc/php.ini
[email protected]:~ # su -m www
[email protected]:~ % file /usr/local/www/nginx/php/phpinfo.php
/usr/local/www/nginx/php/phpinfo.php: PHP script, ASCII text
[email protected]:~ %
and yet still "No input file specified."
-
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.
-
Sandip
Posted: March 15, 2014
Saved my time today ... thanks. SS
-
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 :-)
-
Ed Schroedinger
Posted: March 31, 2015
now, thanx a lot for the 'lazy walk' ;) ...it indeed solved my initial trouble getting php to work via fcgi :)
... moreover, finally migrating from apache, your primer on nginx configuration as well pre-answered some imminent questions before actually stepping over the tripwires
bigup for the nice job, really helped a lot! :)
-
naGt
Posted: April 7, 2015
Thanks _A LOT_ for this usefull information about "Using Alias and $document_root". Two days lost troubleshooting nginx configuration, changing parameters and trying to understand what was going on.
Now it's running like a charm.
Best regards,
Ignacio
-
Asysteo
Posted: May 11, 2015
Hey! i have problem with my page too. After php version update i got error like this "502 Bad Gateway
nginx/1.6.2"
-
bloodynumen
Posted: June 4, 2015
Thx. The open_basedire fix my question.
-
D3lphi
Posted: June 28, 2015
Martin, at first i want to thank you for this great information on your blod *thumbs-up*
I didn't find the culprit and noone on #nginx channel was able to help me either, yet. You pointed at least to the right direction by explaining the difference of fastcgi.conf and fastcgi_params. My issue and configuration is explained here ==> http://p.ngx.cc/f414b76106e81c21
You said, that only "fastcgi_param SCRIPT_FILENAME $request_filename;" will take the use of "alias" into consideration so it can executed by fastcgi, is that correct? How do I modify my configuration to take also into account ...
http://trac.nginx.org/nginx/ticket/321
and
http://wiki.nginx.org/PHPFcgiExample
which suggest NOT to use "try_files" but instead use "if" even then where nginx says that IfIsEvil ?
I'm kinda confused and cannot get this stuff to work and my goal is:
- I want to access all three webapps, and https://example.tld/webapp3/remote.php/webdav should also work (webapp3 is owncloud in my example).
- I want to have the best security context possible so attackers cannot upload and execute malicious code as explained here https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/
- When I remember correctly I should use "cgi.fix_pathinfo = 0" in php.ini, right? that's my actual setting.
- I was also told to use the "split_path" configuration as shown in my actual nginx configuration.
I would be very glad to hear your comments on that and how you suggest me to solve that. Any help appreciated.
Thank you so much in advance.
-
Zaheer Ahmad Khan
Posted: September 12, 2015
Martin awesome info and explanation, you mad my day. Thanks a lot.
-
Zaheer
Posted: January 20, 2016
- I am very new in Nginx...
- I am trying to create multi site using Drupal 7, Nginx on ubuntu 14.4.
- I am applying settings for multi site in given path: "/etc/nginx/sites-enabled/default"
- I saved my drupal setup in: "/var/www/drupal"
- given below is the code, which i am using in "/etc/nginx/sites-enabled/default" file
server {
#listen 80 default_server;
listen [::]:80 ipv6only=off;
root /var/www/drupal;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$args ;
}
location ~ '\.php$|^/update.php' {
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_intercept_errors on;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
}
- I am trying this URL http://mydomain.com/site1, but it redirecting me to http://mydomain.com/install.php
- I need to create URL like: http://mydomain.com/site1.
Thank you so much in advance. Reply please
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.