nginx location directive doesn't look for specified file first - nginx

I have a simple nginx configuration file -
server {
listen 80 default_server;
root /var/www/example.com;
#
# Routing
#
location / { index index.html; }
location /foo { index foo.html }
#
# Logging
#
access_log /var/log/nginx/{{ www_domain }}.log;
error_log /var/log/nginx/{{ www_domain }}-error.log error;
server_name example.com;
charset utf-8;
}
As you can see, there's only 2 routes - the / and /foo paths.
When I go to www.example.com/ all works correctly. I can see the index.html page being served.
When I go to www.example.com/foo, I get a 404 error when I should be getting the foo.html page.
Looking at the logs, I see this error:
2018/08/13 21:51:42 [error] 14594#14594: *6 open() "/var/www/example.com/foo" failed (2: No such file or directory), client: XX.XX.XX.XX, server: example.com, request: "GET /foo HTTP/1.1", host: "example.com"
The error implies that it's looking for a file named /var/www/example.com/foo and not /var/www/example.com/foo.html like I would expect.
Why does this happen in general, and specifically why does it not happen on my root path / ?
Thanks!
Edit: It does work if I visit www.example.com/foo.html directly

The index directive will append the filename, when you give the URI of a directory.
So / points to the root directory (/var/www/example.com/), and the index index.html; statement causes nginx to return the file /var/www/example.com/index.html.
The /foo URI does not point to a directory. If the directory /var/www/example.com/foo/) did in fact exist, the index foo.html; statement would cause nginx to return the file /var/www/example.com/foo/foo.html. Which is not /var/www/example.com/foo.html.
What you are attempting to achieve is some kind of extension-less scheme, which is nothing to do with the index directive.
See this document for details of the index directive.
There are many solutions that will work, for example, using try_files instead of index:
location /foo { try_files /foo.html =404; }
See this document for details.

Related

Try_files directive keeps looking for files in /usr/local/nginx/html

I can't get my head round why my nginx config keeps looking for files in the wrong directory.
I'm trying to map the /files location to /home/user/toto. For that I'm using a regex capture group to remove the /files prefix and search for the files in the directory specified in the root directive.
server {
listen 80;
server_name localhost;
location ~^\/files\/(.*)$ {
root /home/user/toto;
try_files /$1/ /$1 ;
autoindex off;
}
}
The problem is I only get 404s. And that's pretty normal because here is what we can find in error.log :
2022/07/17 11:27:49 [error] 40358#0: *40 open() "/usr/local/nginx/html/test.txt" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /files/test.txt HTTP/1.1", host: "localhost"
As we can see the root directive seems to be completely ignored.
I tried an alternative configuration such as :
server {
listen 80;
server_name localhost;
location ~^\/files\/(.*)$ {
# root /home/user/toto;
try_files /home/user/toto/$1/ /home/user/toto/$1 ;
autoindex off;
}
}
But the problem is still the same. The only change is that the path now appears in the logs as a prefix for the file name :
2022/07/17 11:12:02 [error] 40288#0: *36 open() "/usr/local/nginx/html/home/user/toto/test.txt" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /files/test.txt HTTP/1.1", host: "localhost"
What am I missing ?
Your missing the last parameter from the try_files directive, so that the /$1 is being interpreted as an internal redirect instead of a file term.
Use:
try_files /$1/ /$1 =404;
See this document for details.

Nginx returns 404 after changing root path

I've installed Nginx on my Digital Ocean droplet and I've done a build for my react application, now I want to serve the build index.html file to Nginx,
/etc/nginx/sites-enabled/default:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /root/project-name/dist;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
}
When I visit the server in the browser I get an 404 message.
The path /root/project-name/dist is valid:
If I change the root path to:
root /var/www/html;
Then I get the default Nginx page displayed:
The root and var folder are both in the same path:
So why can't I point my root to a different folder?
Resolved the error.
Step 1. Read the logs (!!)
Nginx: stat() failed (13: permission denied)
My nginx logs are located in /var/log/nginx/. The error.log showed:
2021/10/04 18:18:41 [crit] 1565#1565: *3 stat() "/root/project-name/dist/" failed (13: Permission denied), client: 82.73.195.213, server: _, request: "GET / HTTP/1.1", host: "104.248.82.123"
Step 2. Change access to folders:
chmod +x /root/
chmod +x /root/project-name
chmod +x /root/project-name/dist

Unexpected nginx behavior

I have the following block in my nginx config:
location ~ /$ {
index index.html index.cgi index.pl index.php index.xhtml index.htm index.shtml;
}
location /cat {
try_files /index.php?url=$uri =404;
}
What I expect this to do: Any request sent to http://www.example.com/cat<whatever> will be sent to index.php with the GET variable url set to the request uri. What happens instead based on the rewrite log is that the location /cat block is never hit at all. Here is a relevant excerpt from the rewrite log when I request http://www.example.com/cart/testing/:
2017/03/21 00:32:49 [error] 25711#0: *20566477 "/var/www/vhosts/example.com/httpdocs/cat/testing/index.html" is not found (2: No such file or directory), client: <ip redacted>, server: example.com, request: "GET /cat/testing/ HTTP/1.1", host: "www.example.com"
There are no other entries related to the request.
It was my understanding that nginx processes any prefix location blocks (i.e. location /cat) BEFORE any location blocks involving regex (i.e. location ~ /$). So I'm stumped by this behavior.
Your understanding is incorrect. See this document for details.
Also, your try_files directive is incorrect. Either /index.php?url=$uri or =404 should be the last element in the statement. See this document for details.
You probably want:
index index.html index.cgi index.pl index.php index.xhtml index.htm index.shtml;
location /cat {
try_files $uri $uri/ /index.php?url=$uri;
}
Not sure of the purpose of the other location block, as the index directive is already going to process any URI with a trailing /. See this document for details.

Nginx working with apache-like locations

I am trying to migrate my personal sterver from apache to nginx, but i cant get the location to work.
My server have several apps, avaliable in some /something from root, like url.com/git url.com/mediaWiki, url.com/vnstat url.com/redmine
In apache a have a bunch of config files for each app:
redmine.conf
<Location "/redmine">
Options none
Require all granted
PassengerEnabled On
RailsBaseURI /redmine
RailsEnv production
</Location>
vnstat_php.conf
Alias /vnstat /var/www/vnstat_php
<Directory /var/www/vnstat_php>
DirectoryIndex index.php
Require all granted
</Directory>
I am trying to replicate this on nginx, but my best try so far end up with a weird url. I only manage the thing to work writing on the main ngix config file:
server {
listen 8123 default_server;
listen [::]:8123 default_server;
server_name _;
root /var/www/html;
location / {
}
location /vnstat/ {
root /var/www/vnstat_php/;
index index.php;
}
}
The root page is working ok, but the /vnstat link send me to
2017/02/20 11:37:19 [error] 27538#0: *1 "/var/www/vnstat_php/vnstat/index.php" is not found (2: No such file or directory), client: 177.92.59.216, server: _, request: "GET /vnstat/ HTTP/1.1", host: "url.com:8123"
It is looking for a vnstat directory inside /var/www/vnstat_php/ instead using it as root. Can anyone point me in the right direction?
As described at http://nginx.org/en/docs/http/ngx_http_core_module.html#root
A path to the file is constructed by merely adding a URI to the value of the root directive. If a URI has to be modified, the alias directive should be used.
you should use alias for this case:
http://nginx.org/en/docs/http/ngx_http_core_module.html#alias
location /vnstat/ {
alias /var/www/vnstat_php/;
}
But using PHP with nginx you should consider to work with FastCGI: https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/

NGINX Log request on specific URI

I want to log all request coming from a specific URI. For example, I want to log all request coming from http://test123.com/api/xxxxxxx, with /api.
server {
listen 80;
server_name xxxxxxx;
root /usr/share/nginx/app/public;
index index.php index.html;
location /api{
access_log /var/log/nginx/test.access.log main;
}
}
This code successfully logs the request but returned an error
open() "/usr/share/nginx/app/public/api" failed (2: No such file or directory)
Thank you so much.
location /api is that location exist file and dir. Please check properly files.

Resources