2

I have a issue with my NGINX setting with redirecting to a custom error page on another location (incl. css, images, js) if a error page should be thrown.

At first I would like to block access to an folder (like .git). This can be easily done via (inside the server block)

location ~ /(.git) {
    deny all;
    return 404;
}

Then i created a custom error_page element (inside the server block) with a custom 404.html file on a different location than the root directory of the website.

error_page 404 /404.html;
location = /404.html {
    root /var/data/websites/error-page;
    internal;
}

After these changes, my custom 404 page will be shown - but without css, js and images.

If i inspect the website, the reason is simple: the path of the files are wrong - they are based on the location (in my example .git). https://it.dmetzler1988.io/.git/css/main.css net::ERR_ABORTED 404.

Here is the complete NGINX config file for this page (only removed the ssl certificate paths):

server {
    listen 443 ssl;
    listen [::]:443 ssl http2;

    ssl_certificate <path>;
    ssl_certificate_key <path>;

    server_name it.dmetzler1988.io;
    root /var/data/websites/dmetzler1988.io/it.dmetzler1988.io;
    index index.html index.php;

    error_page 404 /404.html;
    location = /404.html {
        root /var/data/websites/error-page;
        internal;
    }

    location ~ /(.git) {
        deny all;
        return 404;
    }
}

So my questions on this place:

  1. How can i fix the issue with the wrong path (remove the .git from path)?
  2. Is this the correct way for such an use case or is there a better solution?
devKyrios
  • 21
  • 3
  • Welcome to ServerFault. It's best to keep the assets (main.css, main.js, etc) in a separate folder (such as in /example-folder/) and then use an additional location block (`location /example-folder/ { alias "/path/to/example-folder"; }`) with custom root or alias to serve those files. – Pothi Kalimuthu Nov 20 '21 at 01:03
  • 1
    @PothiKalimuthu Your solution requires an `alias /path/to/example-folder/` directive to work properly (note the trailing slash). Without it request like `/example-folder/css/main.css` would be served as `/path/to/example-foldercss/main.css` obviously giving you an `HTTP 404 Not Found` error. I described this `alias` behavior [here](https://stackoverflow.com/a/69296739/7121513). – Ivan Shatsky Nov 21 '21 at 07:34
  • @IvanShatsky I tried it so than you described it (also tried various modifications) but it won't work for my css (used only css path for tests). `location ~* /.git/css/.* { root /var/data/websites/error-page/css; }`. Is there something wrong? I receive the 404 error for this file also after adding the new location. – devKyrios Nov 21 '21 at 22:49
  • @devKyrios Can you add config you tried as an update to your question? – Ivan Shatsky Nov 21 '21 at 22:52
  • @IvanShatsky haha, sorry, was to slow with editing. Is now added. I tried it with and without the `/.*` at the end. Also with case sensitive locations and so on. – devKyrios Nov 21 '21 at 23:02
  • @IvanShatsky oh damn.. sorry, nevermind - my fail. It doesn't work with the location block which i added yesterday ( `location ~ /\.git { return 404; }` ). I have a overlapping location block. Sorry. – devKyrios Nov 21 '21 at 23:16

1 Answers1

0

First, about the errors in your config.

location ~ /(.git) { ... }

Looks you are not quite familiar with PCRE regex patterns. There is no need to use a capture group here - capture groups are used when you'd need its content later. However it isn't a critical error. The worst part is that you use unshielded dot char, which work as wildcard in regex patterns. This way you effectively blocking any URI containing a string where second, third and fourth chars are git (e.g. /agitation/index.html, /any/prefix/agitation/index.html, etc.) The right regex pattern here will be /\.git (blocking anything starting with .git including .gitignore, etc. on any nested directory level).

Next, you are using two directives in that location - deny all and return 404. Only one of them will be sufficient here - either deny all (returning HTTP 403 Forbidden) or return 404 (returning HTTP 404 Not Found). The reason you are getting 404 rather than 403 is that return directive executed at the REWRITE request processing phase while deny one executed at the later ACCESS phase (request processing phases described in the development guide).

Now back to your question. Looks like you are referring your assets using relative URI paths, e.g.

<link rel="stylesheet" type="text/css" href="css/main.css">

Some of your options are (but not limited to):

  • embed every asset into the error handler HTML (including your images, you can do it encoding your images to BASE64 and using the Data URIs);

  • move all the assets to the some folder under your main site webroot (say /var/data/websites/dmetzler1988.io/it.dmetzler1988.io/assets/errors and refer them using the full path:

    <link rel="stylesheet" type="text/css" href="/assets/errors/css/main.css">
    
Ivan Shatsky
  • 2,360
  • 2
  • 6
  • 17
  • At first, thank you a lot for your useful feedback! My knowledge about regex in NGINX seems to be wrong. Also the directive information was very helpful - so i be safe with the `return 404` directive only. Your both ideas to solve the sources issue would be a solution, but I didn't want to duplicate the code and will keep it easily editable/understandable (without base64 encoding and css/js in html). I hope that there exist a solution with root modifications, proxy or similar. Thank you again for your very constructive and helpful feedbacks!! – devKyrios Nov 20 '21 at 22:47