I'm trying to let Nginx serve my authenticated admin users some static files with PHP. This works great, I get back the file. But it's served with a 404 status code..
I'm using the following (Symfony / Silex) php code:
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
$filePath = '/usr/share/nginx/project/src/path/to/my/protected/static/dir/' . $file;
if (empty($file) || !is_readable($filePath)) {
$app->abort(404);
}
$response = new BinaryFileResponse($filePath);
$response->trustXSendfileTypeHeader();
$response->setPrivate();
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_INLINE,
$file,
iconv('UTF-8', 'ASCII//TRANSLIT', $file)
);
$response->headers->addCacheControlDirective('must-revalidate', true);
return $response;
And here's my nginx config:
server {
listen 443;
listen [::]:443;
root /usr/share/nginx/project/web;
index index.php;
error_page 401 403 404 /404.html;
server_name example.com;
rewrite ^/(.*)/$ /$1 permanent;
location / {
# First attempt to serve request as file, then
# as directory, then let php handle the file
try_files $uri $uri/ /index.php$is_args$args;
index index.php;
autoindex off;
location ~* \.(svg|jpg|jpeg|png|gif|ico|css|js)$ {
expires 150d;
}
}
location ~ \.php$ {
set $path_info $fastcgi_path_info;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
try_files $uri $uri/ /index.php$is_args$args;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
include fastcgi_params;
fastcgi_param APP_ENV production;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
The protected dir lies outside of the root in the nginx config (/usr/share/nginx/project/web).
I've found these kind of error messages in the logs:
open() "/usr/share/nginx/project/web/admin/static/admin.js" failed
(2: No such file or directory),
request: "GET /admin/static/admin.js HTTP/1.1"
Where /admin/static/admin.js was indeed the requested url.
Update 1
It looks like nginx always tries to open the url and adds an entry to the error log even php handles the response just fine.
Even if I replace all the php code for just: return new Response('test', 200); the response code for the body 'test' is still 404...
I also tried adding an extra location block in my nginx config:
location /protected_admin_files {
internal;
alias /usr/share/nginx/project/src/path/to/my/protected/static/dir;
}
And then try to redirect to the file like this:
return new Response('', 200, [
'X-Accel-Redirect' => '/protected_admin_files/' . $file
]);
But also without luck. Same 404 with the right response body...
I've found the cause myself..
This was what I found in the error log once I set the error level to debug (here's the full log)
...
[debug] rewrite phase: 1
[debug] http script regex: "^/(.*)/$"
[notice] "^/(.*)/$" does not match "/admin/static/admin.js", request: "GET /admin/static/admin.js HTTP/1.1", host: "example.com"
[debug] test location: "/"
[debug] test location: "protected_admin_files"
[debug] test location: ~ "\.(svg|jpg|jpeg|png|gif|ico|css|js)$"
[debug] using configuration "\.(svg|jpg|jpeg|png|gif|ico|css|js)$"
...
[debug] http filename: "/usr/share/nginx/project/web/admin/static/admin.js"
[debug] add cleanup: 00000000025AE108
[error] open() "/usr/share/nginx/project/web/admin/static/admin.js" failed (2: No such file or directory), client: 24.132.134.203, server: example.com, request: "GET /admin/static/admin.js HTTP/1.1", host: "example.com"
[debug] http finalize request: 404, "/admin/static/admin.js?" a:1, c:1
[debug] http special response: 404, "/admin/static/admin.js?"
[debug] internal redirect: "/index.php?"
...
Apparently, the nested location in my first first location / block was causing the 404.
location / {
try_files $uri $uri/ /index.php$is_args$args;
index index.php;
autoindex off;
location ~* \.(svg|jpg|jpeg|png|gif|ico|css|js)$ {
expires 150d;
}
}
It got matched because of the extension, making Nginx go looking for the file. Since it's then not found, the 404 is set and apparently not overwritten later in the process when php returns the X-Accel-Redirect header :(.
Related
I am using the default config with Nginx installed on my manjaro machine. I just added some simple configurations down below.
nginx.conf:
user http;
worker_processes auto;
worker_cpu_affinity auto;
.....
http{
.....
server {
listen 9000;
server_name localhost;
root /usr/share/nginx/html/exam;
location / {
index index.php index.html index.htm;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
if (!-e $request_filename){
rewrite ^/(.+)$ /index.php?url=$1 break;
}
}
location /. {
return 404;
}
location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
include /etc/nginx/fastcgi.conf;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_intercept_errors on;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_read_timeout 864000;
}
location ~ /\.ht {
deny all;
}
}
....
}
since the user for Nginx is http, I also changed the ownership of the folder, subfolders and files as HTTP with:
chmod -R http:http exam/
it looks like this:
1838248 lrwxrwxrwx 1 http http 42 Eyl 13 17:42 exam
but still gives 403 Forbidden on browser with this error:
2021/09/13 17:49:22 [error] 493923#493923: *4 open() "/usr/share/nginx/html/exam/index.php" failed (13: Permission denied), client: 127.0.0.1, server: localhost, request: "GET /exam HTTP/1.1", host: "localhost:9000"
I have tried every solution I found, but it did not work.
I also tried simple PHP files that runs like "phpinfo();" even they are not working.
I moved the project file under /srv/http and redirect the root in the conf file to it. Now it is working.
I have an issue configuring Nginx correctly to work with Slim POST route.
In a post here on StackOverflow it was said that it is not a good practice to rewrite POST request.
Post: nginx rewrite post data
The idea is to have http://someurl.com/scan which is a POST route in index.php and allow only POST requests on the /scan and deny everything else.
index.php:
$app->post('/scan', function(ServerRequestInterface $request, ResponseInterface $response) { ... }
My Nginx conf looks like this:
server {
listen 80;
server_name someurl.com;
index index.php;
root /var/www/maxime/public;
error_log /var/log/nginx/max.err
access_log /var/log/nginx/max.log
location / {
deny all;
}
location = /scan {
limit_except POST {
deny all;
}
rewrite ^/scan$ /index.php last;
}
location ~ index\.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
include fastcgi_params;
fastcgi_pass php_pool;
fastcgi_keep_conn on;
}
}
To me this conf tells me that if a request is done on /scan and it is a POST request then we "redirect" everything to /index.php. Then the index.php location block comes into action which passes everything to the index.php or am I mistaking somewhere?
Currently with this setup I get this error in Nginx:
*100778 readv() failed (104: Connection re
set by peer) while reading upstream client: 123.123.123.123, server: someurl.com,
request: "POST /scan HTTP/1.1", upstream: "fastcgi://127.0.0.1:9001", host: "someurl.com"
I have a nginx and php-fpm config but when i access it from browser, only index.php is getting executed but rest of the files i am not able to call .
nginx config
{
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
keepalive_timeout 15;
keepalive_requests 2048;
server_tokens off;
upstream php
{
server unix:/tmp/php-cgi.socket;
server serverip:9000;
}
access_log /var/log/nginx/access.log main;
include /etc/nginx/conf.d/*.conf;
}
config in /etc/nginx/conf.d/
server {
root /var/www/Cachet/public/;
location / {
try_files $uri $uri/ /index.php index.php;
}
server_name serverip ; # Or whatever you want to use
listen 80 default;
location ~* \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_keep_conn on;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
These are few lines from error.log and access.log
2015/11/06 12:40:53 [error] 19346#0: *1 FastCGI sent in stderr:
"Unable to open primary script: /var/www/Cachet/public/dashboard.php
(No such file or directory)" while reading response header from
upstream, client: Client IP, server: Server IP, request: "GET
/dashboard.php HTTP/1.1", upstream:
"fastcgi://unix:/var/run/php5-fpm.sock:", host: "Server IP"
2015/11/06 12:41:05 [error] 19346#0: *1 FastCGI sent in stderr:
"Unable to open primary script: /var/www/Cachet/public/autoload.php
(No such file or directory)" while reading response header from
upstream, client: Client IP, server: Server IP, request: "GET
/autoload.php HTTP/1.1", upstream:
"fastcgi://unix:/var/run/php5-fpm.sock:", host: "Server IP"
since there was no response here then with help from my colleague i was able to find two problem here in config file because of which i was not able to call multiple php files in separate folder ..
try_files $uri $uri/ /index.php index.php;
instead it needed
try_files $uri $uri/ /index.php$is_args$args;
Alos since it was not loading the images the line which was missing was
include /etc/nginx/mime.types; in location block of conf.d/default.conf.
Check if your installed PHP version and PHP version inside config.d do not match each other. If that is the case, change PHP version inside conf.d file to your installed PHP version. Reload nginx.
fastcgi_pass unix:/var/run/php5-fpm.sock;
server {
listen 80;
server_name myapp.local
root /home/jack/Documents/projects/php/myapp/web;
location / {
#try_files $uri $uri/ /app_dev.php?$query_string;
#try_files $uri /app_dev.php$is_args$args;
try_files $uri #rewriteapp;
}
location #rewriteapp {
rewrite ^(.*)$ /app_dev.php/$1 last;
}
location ~ ^/(app|app_dev|config)\.php(/|$) {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
access_log /var/log/nginx/myapp-access.log;
error_log /var/log/nginx/myapp-error.log;
}
I've been trying to make this work but I couldn't and when I go to myapp.local I got No input file specified.. In the logs I have:
[error] 6867#0: *1 FastCGI sent in stderr: "Unable to open primary script: /usr/share/nginx/html/app.php (No such file or directory)" while reading response header from upstream, client: 127.0.0.1, server: myapp.local, request: "GET /app.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "myapp.local"
UPDATE
It looks like it's trying to access /usr/share/nginx/html/app.php, why in the world is it doing that?
nginx -v : 1.4.6
Believe it or not guys, after 4 hours of debugging I realized that it was all about a poor missing semicolon after server_name statement. What a shame!
I just switched from apache to nginx, just for testing and I experience the following problem. I am using this config for nginx
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
Now I have a php script makethumbs.php that automatically resize images displayed on my website. With apache, works just fine. With nginx I get this error:
2011/12/29 15:13:17 [error] 15548#0: *9 open() "/usr/share/nginx/html/makethumbs.php/0737438664-22.jpg" failed (20: Not a directory), client: 193.138.192.81, server: www.escortele.eu, request: "GET /makethumbs.php/0737438664-22.jpg?width=48&height=64&image=/members/escorte/0737438664-22.jpg HTTP/1.1", host: "escortele.eu:88", referrer: "http://escortele.eu:88/"
The problem is that it sees makethumbs.php as a directory and it should be a script not a directory.
I can't figure it out what rewrite rule to use, only for makethumbs.php so it acts like a script and not like a directory.
You should have pasted the rest of your configuration file because what you pasted has nothing to do with what you want.
That error is because you have "try_files $uri $uri/ /index.php;" somewhere in your config. You need to remove the $uri/ from that to fix the error you pasted.
The problem is not in
location / {
try_files $uri $uri/ /index.php;
}
That part is good. You need it.
Since you didn't post your entire config I can't be sure what you're problem is, but I can tell you what my problem was in the same type of situation. Following the recomendation of others, I had a location defined for image files as follows:
location ~* \.(jpg|jpeg|png|gif|css|js|ico)$ {
expires max;
log_not_found off;
}
That was the problem. Because Nginx uses the most specific location that matches, the URL ending with .jpg would match this location and this location doesn't tell it to use index.php. I just got rid of this location and it worked.
Additional tips:
define your root in the server block and not in location blocks.
I don't think you don't need "fastcgi_index index.php;"
You don't need to hard-code your document root:
change
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
to
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
This is the script I am using for thumbnails: http://escorte.pro:88/makethumbs.txt
My nginx config is as follows: http://escorte.pro:88/nginx.txt
The error I get is:
2014/08/27 14:59:07 [error] 20986#0: *86 open() "/usr/share/nginx/html/escorte.pro/makethumbs.php/0737835261-79.jpg" failed (20: Not a directory), client: 83.166.220.234, server: escorte.pro, request: "GET /makethumbs.php/0737835261-79.jpg?width=48&height=64&image=/members/escorte/0737835261-79.jpg HTTP/1.1", host: "escorte.pro:88", referrer: "http://escorte.pro:88/"
2014/08/27 14:59:07 [error] 20986#0: *87 open() "/usr/share/nginx/html/escorte.pro/makethumbs.php/0743844296-60.jpg" failed (20: Not a directory), client: 83.166.220.234, server: escorte.pro, request: "GET /makethumbs.php/0743844296-60.jpg?width=48&height=64&image=/members/escorte/0743844296-60.jpg HTTP/1.1", host: "escorte.pro:88", referrer: "http://escorte.pro:88/"
The makethumbs.php script works perfectly fine on apache
Any clues?
I hope this info si more complete than the previous...