NGINX vs PHP-FPM: No input file specified
We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.
NGINX PHP-FPM essentials
When you configure NGINX against PHP-FPM, what you really do is teach NGINX where is PHP-FPM listening and what kind of information has to be delivered to it.
NGINX does not do any processing of PHP scripts of its own. It merely talks to PHP-FPM and says:
This couple works well together. On a website with SEO-friendly URLs, NGINX does the job of rewriting request URL in order to construct and pass the proper filename to PHP-FPM. And PHP-FPM does the heavy lifting of parsing the script, running it and delivers resulting HTML back to NGINX.
In general, aside from some extra bits of information like environment variables, NGINX delivers one important piece of information to PHP-FPM – the filename of the script.
The standard bit of configuration illustrates it:
NGINX does not even need to have read access to the .php file in question in order to have it properly launched via PHP-FPM and then displayed to clients.
So this chmod in your site setup may be perfectly valid:
-- site ----- index.php (chmod 0400, chown user:user) ----- style.css (chmod 0640, chown user:nginx)
Note how NGINX has no access for index.php whatsoever, yet the page will work just fine in our setup.
Let’s expand to another case, our case of interest for this post.
What would happen when someone visits a non-existent .php file? NGINX will happily pass it along to PHP-FPM as usual, and PHP-FPM will return the dreaded:
This error is emitted by NGINX to the client’s browser. Because that’s what PHP-FPM happens to produce when you give it a filename that doesn’t exist.
Well, it’s a 404 error. Why bother? Sure enough, that’s not really the kind of error you want your users to see.
So in this post, I will tell you what are the dos and don’ts in fixing this error. That is, aside from obvious misconfiguration you might have.
Our case is when the script file is really not there. In other words, let’s see what is the best configuration approach to handling 404s for requests to missing .php files. And showing something better looking than No input file specified .
Solution on the PHP-FPM side? None that I know
There’s no way to customize the message. Well, in theory, you can patch and recompile PHP like those poor folks who like to play with NGINX compilation.
So let’s move on to NGINX. There are multiple ways to solve it there, and I tell you this – there are too many ways to do things inherently wrong. Use the power that NGINX gives you wisely.
Solutions in NGINX
Going down from worst to best.
Worst
You may have seen this one:
location ~ \.php$ < if (!-e $request_filename) < rewrite / /index.php last; >## Catch 404s that try_files miss . fastcgi_pass unix:/path/to/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params;
The idea is to check if .php script is really there, then rewrite to /index.php , which is supposed to know how to display 404 nicely (some CMS framework). Cute, nah?
You know why it’s already bad: if is evil. We all already know that blah blah.. Give me a break 🙂
But what would happen if we retain our very secure chmod ( 0400 on .php files) that we began our post with? We’ll get error upon accessing any .php file:
rewrite or internal redirection cycle while internally redirecting to “/index.php
All simply because it has no access for .php files.
Come on, just let NGINX read the .php files. It’s OK. Just let it be.
Well, I don’t want to if I can. There is never enough security. And secure chmod is something essential. Let’s keep trying.
So how about …
That’s cuter. No if s, just try_files . All as per NGINX ninja style. But wait, how about having the error page displayed by your PHP framework? Doable also with:
Stop right there. We’re still letting NGINX check file for existence, so it’s still going to fail if it has no access to the scripts in our secure setup.
Best solution
location = /404.php < fastcgi_intercept_errors off; fastcgi_pass unix:/path/to/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; . >location ~ \.php$ < error_page 404 /404.php; fastcgi_intercept_errors on; fastcgi_pass unix:/path/to/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; . >
We tell NGINX what page to display upon receiving 404 from PHP-FPM, here: error_page 404 /404.php; .
We have to set up a dedicated location for /404.php because we know this script exists (you have to create it, of course, if your framework has none; and it must be different from the front page handler like index.php ). We don’t want to discard PHP-FPM output for it, so we put fastcgi_intercept_errors off; . Which is the default, so can be omitted but kept for illustration of what happens there.
Now NGINX doesn’t need to check for script existence. PHP-FPM will be the one to tell it.
So there you have it: a clean, tidy solution to 404 pages on missing .php script files in NGINX. It’s also secure and allows for lockdown chmod.
nginx No input file specified.
не судите строго впервые работаю с nginx. хочу настроить связку nginx+php-fpm. При открытии файла .php в браузере вот такая ошибка No input file specified.
server < listen 80; server_name lan-ip.ru; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / < root /var/www/lanip; index index.php index.html index.htm; >location ~ \.php$ < fastcgi_pass unix:/run/php/php7.2-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; ># deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht < # deny all; #>>
не могу понять что такое и откуда здесь SCRIPT_FILENAME в fastcgi_params его нету.
cat /etc/nginx/fastcgi_params fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200;
Подскажите что делаю не правильно и какие ещё конфиги показать?
NGINX — No input file specified. — php-fpm
The error is described in the title. The problem is that it’s all ok with .php files, but I can’t serve .html files (403 error). Nginx and php-fpm are working like www-data user, owner group for all the site directory is www-data , permission for the file I’m testing is 775. Everything is working fine if I rename index.html to index.php . My vhost config:
server < listen 80; server_name www.martynov.test.kooweb.ru martynov.test.kooweb.ru; root /home/martynov/www/test.kooweb.ru; access_log /var/log/nginx/martynov.test.kooweb.ru.access.log; index index.html index.htm index.php; location / < try_files $uri $uri/ /index.php; ># serve static files directly location ~* \.(jpg|jpeg|gif|css|png|js|ico|map|coffee|svg)$ < access_log off; expires max; >location ~ /\.ht < deny all; >location ~* \.php < try_files $uri =404; include common/php-fpm; >>
fastcgi_pass php-fpm; include fastcgi_params; fastcgi_split_path_info ^(.+?\.php)(/.*)?$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name; set $path_info $fastcgi_path_info; fastcgi_param PATH_INFO $path_info; fastcgi_param SERVER_ADMIN email@example.com; fastcgi_param SERVER_SIGNATURE nginx/$nginx_version; fastcgi_index index.php;
UPD There are messages which are added to nginx error log:
[error] 26452#26452: *275 FastCGI sent in stderr: «Unable to open primary script: /show5/index.php (No such file or directory)» while reading response header from upstream, client: , server: , request: «GET /show5/ HTTP/1.1», upstream: «fastcgi://unix:/run/php/php7.1-fpm.sock:», host: «»
[error] 26452#26452: *278 FastCGI sent in stderr: «Access to the script ‘/show5/index.html’ has been denied (see security.limit_extensions)» while reading response header from upstream, client: , server: , request: «GET /show5/index.html HTTP/1.1», upstream: «fastcgi://unix:/run/php/php7.1-fpm.sock:», host: «»
I have no idea how to fix this.
NGINX — No input file specified
The aim: Run two apps under one domain, first app on the root (/) and second app under the URI (/learn).
http://example.com/ - first app http://example.com/learn - second app
The problem: The main app works perfectly, but the learn app is showing a white page with «No input file specified.». My file structure:
/srv/users/serverpilot/apps/main/public/index.php /srv/users/serverpilot/apps/learn/public/index.php
root "/srv/users/serverpilot/apps/main/public"; location ^~ /learn < root "/srv/users/serverpilot/apps"; try_files $uri /learn/public/index.php?$query_string; location ~ \.php$ < add_header X-debug-message $document_root$fastcgi_script_name always; include fastcgi_params; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/srv/users/serverpilot/run/learn.php-fpm.sock; >> location / < try_files $uri $uri/ /index.php?$args; location ~ \.php$ < include fastcgi_params; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/srv/users/serverpilot/run/main.php-fpm.sock; try_files $uri =404; >>
- I know the fastcgi_pass sockets are working because I’ve been running these two apps under different domains but in the same server in question.
- I added the add_header X-debug-message $document_root$fastcgi_script_name» always; to see what the response header would show, and it shows that the SCRIPT_FILENAME is /srv/users/serverpilot/apps/learn/public/index.php which exists and is the exact file I am trying to run.