Nginx is serving the default content instead of my content - nginx

I have a nginx version: nginx/1.10.3 (Ubuntu) running on Ubuntu 16.04.2 LTS.
I use nginx to serve static files, bundles generated by webpack, but that's irrelenvant.
What I want to achieve is this:
On example.com I want to serve /home/bundles/main/index.html. I can do this.
On projects.example.com/project_1 I want to serve /home/bundles/project_1/index.html.
On projects.example.com/project_2 I want to serve /home/bundles/project_2/index.html.
The last two, I can't do. When I go to projects.example.com/project_1 or projects.example.com/project_2 I am served the default nginx page.
To make things more confusing /etc/nginx/sites-enabled/default is entirely commented out.
Additionally, if in the location block of projects.example.com I replace, for example, project_1 with /, I will be served that specific project, but then I will have no way of serving the other.
Bellow, I will show you my nginx configuration
server {
listen 80;
server_name example.com;
location / {
root /home/bundles/main;
try_files $uri /index.html;
}
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name example.com;
location / {
root /home/bundles/main;
try_files $uri /index.html;
}
ssl_certificate ...
ssl_certificate_key ...
}
server {
listen 80;
server_name projects.example.com;
location /project_1 {
root /home/bundles/project_1;
try_files $uri /index.html;
}
location /project_2 {
root /home/bundles/project_2;
try_files $uri /index.html;
}
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name projects.example.com;
location /project_1 {
root /home/bundles/project_1;
try_files $uri /index.html;
}
location /project_2 {
root /home/bundles/project_2;
try_files $uri /index.html;
}
ssl_certificate ...
ssl_certificate_key ...
}
Thank you for your help!
EDIT
My Answer
The solution I found was to change the root with alias.
server {
listen 80;
server_name example.com;
location / {
root /home/bundles/main;
try_files $uri /index.html;
}
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name example.com;
location / {
root /home/bundles/main;
try_files $uri /index.html;
}
ssl_certificate ...
ssl_certificate_key ...
}
server {
listen 80;
server_name projects.example.com;
location /project_1 {
alias /home/bundles/project_1;
index index.html;
}
location /project_2 {
alias /home/bundles/project_2;
index index.html;
}
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name projects.example.com;
location /project_1 {
alias /home/bundles/project_1;
index index.html;
}
location /project_2 {
alias /home/bundles/project_2;
index index.html;
}
ssl_certificate ...
ssl_certificate_key ...
}
The solution is based on these two answers. The first answer showing how to solve the problem and the second answer providing a explanation as to why alias works and root does not.
To quote #treecoder
In case of the root directive, full path is appended to the root including the location part, whereas in case of the alias directive, only the portion of the path NOT including the location part is appended to the alias.
In my particular case, this would translate like this;
With root, the path nginx would try to access would be /home/bundles/project_1/project_1.
With alias it accesses the correct path, /home/bundles/project_1.
Going back one level, for example, saying:
root /home/bundles/ is not really a option either. That is because my projects are not actually called project_1 and project_2. The actual structure is more similar to this.
In /bundles I have the directories project_a and project_b. I want to route project_1 to the project_a directory and project_2 to the project_b directory.
That is why I used alias.
I hope this helps.

You have:
location /project_1 {
root /home/bundles/project_1;
try_files $uri /index.html;
}
So the root is only defined for URIs that begin with /project_1. For any other URI, the default root will be used.
If you present the URI /project_1/ (with a trailing /), assuming that the default index directive is in force, nginx should return your /project_1/index.html content.
However, the URI /project_1 is not found - so /index.html is returned instead. The URI /index.html does not begin with /project_1, so the default root is used.
If you want the URI /project_1 to work as expected, and the default action to go to the project's index.html file, change the try_files directive.
location /project_1 {
root /home/bundles/project_1;
try_files $uri $uri/ /project_1/index.html;
}
See this document for more.
As both projects share a common root, you could simplify as follows:
server {
listen 80;
server_name projects.example.com;
root /home/bundles
index index.html;
location /project_1 {
try_files $uri $uri/ /project_1/index.html;
}
location /project_2 {
try_files $uri $uri/ /project_2/index.html;
}
location / {
deny all;
}
}
I added the index directive to avoid relying on the default value (which is the same), and a location block to deny access to areas outside of the projects.

I had the same problem...and it turned out, for me, that the default site that was "overtaking" my desired secondary site and serving the default files...well it allowed IP6 requests, and my new site didn't.
Here's an example of my access.log:
::1 - - [05/Sep/2020:15:05:16 -0600] "GET / HTTP/1.1" 200 40 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"
Notice the ::1 bit? That's an IP6 request that I guess my browser was defaulting to. So I just made sure to enable local IP6 requests for the site in question in my site config file by changing:
listen 80;
server_name example.local;
to:
listen 80;
listen [::]:80;
server_name example.local;
That was it.

Related

nginx: how to use multiple roots for multiple locations, including / ? (what's wrong with my paths config?)

I'm trying to setup nginx for first test uses, without a domain yet.
My current goal is to show some page at http://<server IP> and serve some static content at http://<server IP>/projectname. The "some page" is currently just the default /var/www/html/index.nginx-debian.html.
In /etc/nginx/sites-available/ I've created a projectname config and I've put a link to sites-enabled:
sudo ln -s /etc/nginx/sites-available/tiddlywiki /etc/nginx/sites-enabled/
The first version of config was
server {
listen 80;
listen [::]:80;
server_name <server IP>;
root /some/path/to/project/static-files;
index index.html;
location /projectname {
try_files $uri $uri/ =404;
}
}
What I got, is http://<server IP> started serving static files, but http://<server IP>/projectname showed 404. How do I fix that? Because next step, I've followed this answer and tried to set 2 locations:
location /projectname {
try_files $uri $uri/ =404;
}
location / {
root /var/www/html;
index index.nginx-debian.html;
}
but only got the default page at http://<server IP> back again, and 404 at http://<server IP>/projectname.
Ok, so the problem was, with root directive, path is concatenated to the root, so with this config
server {
listen 80;
listen [::]:80;
server_name <server IP>;
root /some/path/to/project/static-files;
index index.html;
location /projectname {
try_files $uri $uri/ =404;
}
location / {
root /var/www/html;
index index.nginx-debian.html;
}
}
nginx tried to serve /projectname → /some/path/to/project/static-files/projectname which is an unexisting folder (existing one is /some/path/to/project/static-files). What I needed is the alias directive:
server {
listen 80;
listen [::]:80;
server_name <server IP>;
index index.html;
location /projectname {
alias /some/path/to/project/static-files;
index index.html;
}
location / {
root /var/www/html;
index index.nginx-debian.html;
}
}
I'm not sure how exactly try_files works so I've removed it for now and also added the index directive.

Multiple roots nginx

Is it possible to have a suburl that point to a different root? For example:
www.domain.com/ -> /home/ubuntu/project1
www.domain.com/project2 -> /home/ubuntu/project2
I have this configuration at this moment but I'm getting a 404 when resolving domain.com/project2
server {
listen 80;
server_name domain.com;
root /home/ubuntu/project1;
location /project2 {
root /home/ubuntu/project2;
index index.html;
}
location / {
try_files $uri $uri/ /index.html;
}
}
It's because nginx will append the uri to root directive.
In your example config, accessing domain.com/project2 would try to look for a file named project2 in /home/ubuntu/project2 which is not found and return 404.
To solve your problem, try using alias directives.
server {
listen 80;
server_name domain.com;
root /home/ubuntu/project1;
location /project2 {
alias /home/ubuntu/project2;
index index.html;
}
location / {
try_files $uri $uri/ /index.html;
}
}

Nginx route with single page app

I'm starting to go nuts at this. For some reason, routing wont work on my single page application. So www.example.com works, but not www.example.com/service. I read a lot of posts on how to fix it, but nothing seems to work.
This is my config file at /etc/nginx/conf.d/App.conf
server {
listen 80;
server_name example.com *.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /path/to/certificate/;
ssl_certificate_key /path/to/certificate/key;
root /var/www/App/public;
index index.html;
location / {
try_files $uri /index.html;
}
ssl_session_timeout 5;
}
I have tried all kind of different "location" routes, and nothing seems to work. I do also restart the service with "sudo service nginx restart" everytime I change.
Any clues?
In the comments you said there's a small fixed set of possible routes. In that case you can add a location block for each route, with an alias to the top-level, for example,
location / {
try_files $uri $uri/ =404;
}
location /services {
alias /var/www/App/public;
try_files $uri $uri/ =404;
}
Edit: Or, if you want to serve the top-level index.html in response to any request at all,
location / {
try_files /index.html =404;
}

nginx root directive causing 404

I ham trying to make http://example.com serve http://example.com/home.html from /home/ubuntu/mysitedir/home.html.
I have the following conf file which successfully redirects everything to https, and proxies to uwsgi. The http->https redirection works fine, and the uwsgi proxy works, but http(s)://example.com/, http(s)://example.com/home.html, http(s)://example.com/index.html, and http(s)://example.com/index.htm are all 404
Any pointers as to what I can try?
Here is my conf file:
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
root /home/ubuntu/mysitedir/;
index home.html;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example_combined.crt;
ssl_certificate_key /etc/nginx/ssl/www.example.com.key;
root /home/ubuntu/mysitedir/;
index home.html;
location /images/ads {
alias /home/ubuntu/mysitedir/images/ads/;
}
location /images {
alias /home/ubuntu/mysitedir/images/;
}
location /static {
alias /home/ubuntu/mysitedir/static/;
}
location / {
alias /home/ubuntu/mysitedir/;
include uwsgi_params;
uwsgi_pass unix:/tmp/mysitedir.sock;
}
}
Thanks.
location / is the catch-all. You could try the try_files directive like this:
location #wsgisite {
include uwsgi_params;
uwsgi_pass unix:/tmp/mysitedir.sock;
}
location / {
index home.html;
try_files $uri $uri/ #wsgisite;
}
Any thing coming into the base location will first check to see if it is a file, or a directory with an index (home.html) file in it, and if not, then pass it on to the #wsgisite.
This should also make the other three location directives obselete, since nginx will be checking for the files first before passing it to the wsgi block.

nginx ignores location definitions using regular expressions

I got the following domain configuration on my nginx server (nginx 1.2.1):
server {
listen 80 default_server;
server_name example.com;
root /var/www/example.com;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location ~ /content/(.*)\.(txt|md) {
return 301 /error;
}
location ~ /tpl/(.*) {
return 301 /error;
}
location ~ /sys/(.*) {
return 301 /error;
}
location / {
index index.php
try_files $uri $uri/ /index.php;
}
}
As you can see, I want to disallow access to all .txt/.md files in my content directory as well as every access to my /tpl and /sys directories. But, nginx seems to ignore each one of these rules.
So I tried something different, i.e.:
location ^~ /templates {
return 404;
}
As this works, I guess there's a precedence-problem. Does anybody know how the apply all 3 rules?
Thanks!
— Max

Resources