Nginx - homepage redirects to /index - nginx

I am trying to configure nginx to serve pure static html pages. I am using Ubuntu 18.04.
The issue is as follows:
When trying to enter my website by url: http://www.mywebsite.com/ it changes URL automatically to http://www.mywebsite.com/index .
When using http://www.mywebsite.com/index.html it also changes URL to http://www.mywebsite.com/index - but I assume it's because of the rewrite rule which removes the .html extension from uri.
I would like to remove the silly "/index" ending when using both "/" and "index.html". I have found a solution, but not sure though if it's a "proper" one:
# If URI equals '/' then find index.html static page
location = / {
try_files /index.html $uri =404;
}
# After rewrite homepage URI equals '/index', it rewrites it to '/'
location = /index {
rewrite /index / permanent;
}
I have attempted to configure it by using simple try_files without any rewrites, returns etc. But still it always changed URI to "/index" no matter what, for the homepage.
My configs:
sites-available/mywebsite.com content
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# remove the .html extension from request URI
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
root /var/www/mywebsite.com;
index index.html;
# redirect rules for homepage '/', removes 'index' from URI
include /etc/nginx/sites-available/conf/redirects-homepage-template.conf;
# rule for any URI content. Searches for static file with .html extension or exact URI content file name. If not found, returns 404.
location / {
try_files $uri.html $uri =404;
}
}
redirects-homepage-template.conf content
# Rules for handling homepage redirects
# If URI equals '/' then find index.html static page
location = / {
try_files /index.html $uri =404;
}
# After rewrite homepage URI equals '/index', it rewrites it to '/'
location = /index {
rewrite /index / permanent;
}
The website is meant to serve only static content and it's suppose to work as fast as possible. I wonder about the consequences of my solution and if there's any better way of removing the silly "/index" from homepage.
Haven't configured domain yet, using bare ip address for testing purpose.

Related

NGINX Only path equals to without trailing slash and starts with path with trailing slash

I'm encountering an annoying error when it comes to my current NGINX app configuration.
I have a static web app which I am indexing on the path /admin/*. I want the index to be available on /admin, with and without a trailing slash, as well as available on a wildcard /admin/* (anything after the trailing slash).
The issue I am facing is that the index is accessable when appending anything after the admin path, for example /adminA/example.
The original NGINX configuration was as follows:
location /admin {
alias /home/user/app/static;
index index.html;
try_files $uri $uri/ /index.html;
}
The best I've been able to implement to stop this at the moment is as follows, however i'm sure it can be done more efficiently:
location = /admin {
alias /home/user/app/static;
index index.html;
try_files $uri $uri/ /index.html;
}
location /admin/ {
alias /home/user/app/static/;
index index.html;
try_files $uri $uri/ /admin/index.html;
}
The two location blocks are already efficient, but you could eliminate the redundant code in the first block by redirecting to the second.
Using an internal redirect will be invisible to the browser. For example:
location = /admin {
rewrite ^ /admin/ last;
}
location /admin/ {
...
}
Or use permanent instead of last for an external redirect, which will change the browser's address bar from /admin to /admin/. See the rewrite documentation.

Strange Nginx behavior with trailing slashes

I've got a quite interesting behavior. I want to avoid trailing slashes in URL's on my site. I've put rewrite ^/(.*)/$ /$1 permanent; rule into my server block, so
https://example.com/something/,
https://example.com/something////
redirect to
https://example.com/something;
and
https://example.com/
redirects to
https://example.com
But https://example.com//// is redirected to ... https://enjoygifts.ru//// (actually don't redirected, it's 200 code). Why?
Here is my server block:
server {
listen 443 ssl;
...
... ssl directives
...
root /var/www/mysite.com;
index index.php;
server_name mysite.com;
rewrite ^/(.*)/$ /$1 permanent;
location / {
rewrite ^/.*$ /index.php last;
}
location ~ ^/index.php {
try_files $uri =404;
include /etc/nginx/fastcgi.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
location ~ ^/storage/app/uploads/public { try_files $uri 404; }
...
... lot of similar location blocks
...
}
https://example.com doesn't really exist, the root URI is / - how it's displayed in the browser's address bar is browser dependent - some will automatically show the solitary / whereas others will remove a solitary /.
So you cannot redirect from https://example.com/ to https://example.com - it will be silently interpreted as a redirect from https://example.com/ to https://example.com/.
Nginx uses a normalized URI when evaluating location and rewrite statements, and generating the $uri variable. Multiple consecutive occurrences of / are folded into a single /.
Although the regular expression ^/(.*)/$ matches the URI //, the statement will never see it. Because Nginx has already normalised that URI to /, which does not match the regular expression.
If a root URI with multiple /s is a problem, apply a regular expression to the $request_uri variable, which contains the original URI before normalization and also includes the query string (if any).
For example:
if ($request_uri ~ "^/{2,}(\?|$)") {
return 301 /$is_args$args;
}
This can be placed inside your location / {...} block. See this caution on the use of if.

Nginx try_files not working for default index.html

I am using $geoip_country_code module of nginx to redirect user based on IP. My config code is as given below-
server {
listen 80;
gzip on;
server_name example.com;
root html/example;
location / {
index index.html;
try_files /$geoip_country_code/index.html /index.html;
}
location ~* \.(gif|jpg|jpeg|png|js|css)$ { }
}
Idea is to redirect the user based on country for which I have localised otherwise the user goes to default index i.e generic for everyone else. It works perfectly when opened in browser from my country as I have localised for it. But when opened from a different country it shows internal server error. Its not going to default index page.
Can someone point me what am I doing wrong?
The last element of the try_files statement is the default action, which is either a URI or a response code. The /index.html starts a search for a new location to process the request, and ends up back at the start, so you have a redirection loop.
You can fix the problem by making /index.html a file term instead. For example:
try_files /$geoip_country_code/index.html /index.html =404;
The =404 is never actioned, because /index.html always exists.
Personally, I would use a generic solution:
try_files /$geoip_country_code$uri $uri /index.html;
See this document for more.

nginx config with spa and subdirectory root

I always seem to have problems with nginx configurations. My SPA is located at /mnt/q/app (pushstate is enabled) and the frontend root is located at client/public. Everything should be mapped to index.html, where the app picks up the route and decides what to do.
Full path to the index is /mnt/q/app/client/public/index.html.
I think I ran out of options by now. No matter what I do, I just get a 404 back from nginx, I think the configuration is simple enought and have no clue what's wrong.
server {
listen 80;
server_name app.dev;
root /mnt/q/app;
location / {
root /client/public;
try_files $uri #rewrites =404;
}
location #rewrites {
rewrite ^(.+)$ /index.html last;
}
}
Any help is appreciated.
If nginx views the file system from the root, then the root should be set to /mnt/q/app/client/public, and not either of the two values you are using.
The last element of the try_files directive can be a default action (e.g. /index.html), a named location or a response code. You have a named location in the penultimate element - which will be ignored.
Your named location should work, but is unnecessary, as try_files is capable of implementing it more simply. See this document for more.
For example:
root /mnt/q/app;
location / {
root /mnt/q/app/client/public;
try_files $uri $uri/ /index.html;
}
location /api {
}
location /auth {
}
The $uri/ element will add a trailing / to directories, so that the index directive can work - you do not have to add it if you do not need it.

Nginx rewriting pushstate static resources wont load

I am trying to get nginx to work with a pushstate based uri handled by react-router.
Everything works fine until I try to F5 on a second level uri example.com/MyApp/users.
My static resources are in example.com/MyApp/resources.
The problem is that nginx is trying to load my resources in example.com/MyApp/users/resources whenever I try to access directly (or F5) the users's view.
Here is my nginx conf :
location ~ ^/MyApp/ {
try_files $uri /MyApp/index.html last;
}
I am new to nginx so I don't really know how everything works...
EDIT :
I changed my conf to this:
location / {
if (!-e $request_filename){
rewrite ^(.*)$ /MyApp/index.html break;
}
}
Now accessing to example.com/MyApp/users works but example.com/MyApp/users/ doesn't.
With client side app paths:
/
/foo
/foo/bar
/foo/bar/baz
/foo/bar/baz/123
/tacos
/tacos/123
Use nginx configuration:
server {
listen 80;
server_name example.com;
root /var/www/example.com;
gzip_static on;
location / {
try_files $uri $uri/ /index.html;
}
# Attempt to load static files, if not found route to #rootfiles
location ~ (.+)\.(html|json|txt|js|css|jpg|jpeg|gif|png|svg|ico|eot|otf|woff|woff2|ttf)$ {
try_files $uri #rootfiles;
}
# Check for app route "directories" in the request uri and strip "directories"
# from request, loading paths relative to root.
location #rootfiles {
rewrite ^/(?:foo/bar/baz|foo/bar|foo|tacos)/(.*) /$1 redirect;
}
}
This configuration will work within a pushState "directory" such as example.com/foo/bar/baz/213123 and resolve static files at relative paths like js/app.js to example.com/js/app.js instead of example.com/foo/bar/baz/js/app.js.
For cases with directory depth beyond the first level such as /foo/bar/baz, note the order of the directories declared in the #rootfiles directive: the longest possible paths need to go first, followed by the next shallower path /foo/bar and finally /foo.
See this related answer to a similar question regarding Backbone.
I think you will have to do something like this:
location ~ ^/MyApp/ {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.html =404;
}
location ~ ^/MyApp/resources {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /resources/index.html =404;
}

Resources