2

I'm trying to make a custom 404 error with nginx.

First in my local machine I added the following lines to the default site:

 error_page 404 /custom_404.html;
    location = /custom_404.html {
            root /usr/share/nginx/html;
            internal;
    }

Then in the /usr/share/nginx/html folder I created a nes file named custom_404.html.

Then I went to my development machine and tried to do the same but with aout any luck.

One of the things that I noticed is that in local I'm using the 1.9.3 version and in the development enviroment the 1.2.1 version, and also that the html forlder (/usr/share/nginx/html) doesnt exists.

And the last thing is that in development I use nginx for django aplications so my config file it's something like this:

server {
listen 80;
server_name test.example.net;

# output compression saves bandwidth
gzip  on;
gzip_http_version 1.1;
gzip_vary on;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

client_max_body_size 10M;

if ($http_user_agent ~* '(blackberry|
    iemobile|iphone|ipod|mobile|Mobile|
    nokia|opera\s+mini|smartphone|symbian|webOS)') {
    set $mobile on;
}

if ($http_user_agent ~* 'ipad'){
    set $mobile off;
}

if ($host = example.net) {
    rewrite ^(.*)$ http://www.example.net$1 permanent;
}

if ($uri = '/') {
    set $home_es on;
}

if ($http_referer ~* ^http://test.example.net){
    set $home_es off;
}

if ($home_es = on) {
    rewrite ^(.*)$ /es$1 permanent;
}

gzip_buffers 16 8k;
gzip_disable "MSIE [1-6].(?!.*SV1)";

# media - folder in uri for admin static files
location /newmedia/ {
    expires 30d;
    root /media/jumbo_project;
}
location /media/ {
    expires 30d;
    alias /home/jumbo/media/jumbo_project/newmedia/;
}
location /static/ {
    expires 30d;
    root /media/jumbo_project;
}

error_page   502 503 504 500 /50x.html;

location /50x.html {
    internal;
}

location / {
    proxy_pass  http://localhost:8000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 60;
}

log_format log_time '$request_time $remote_addr - $remote_user [$time_local]  '
    '"$request" $status $body_bytes_sent '
    '"$http_referer" "$http_user_agent"';

access_log  /var/log/nginx/jumbo-wsgi.access.log log_time;
error_log   /var/log/nginx/jumbo-wsgi.error.log;

I've run out of google results to try so if someone can give me a lead to proceed it would be great.

1
  • I found searching another aproach on the internet that it may have something to do with the proxy, especialy with the proxy_intercept_errors. Tried it but when I add the error_page 404 = @fallback; it gives me a 502 bad gateway error.
    – Madox
    Apr 14, 2016 at 14:01

3 Answers 3

2

Well, if the folder /usr/share/nginx/html didn't exist, where did you put the error file then? Nginx serves files from whatever folder you like, you just have to tell it which one. That's why you use the root directive.

So, either create the folder /usr/share/nginx/html and put the file there or put it to e.g. /what/ever/folder and change your configuration to

error_page 404 /custom_404.html;

location = /custom_404.html { 
    root /what/ever/folder; 
    internal;
}

Simple, huh?

OK, not so simple. I don't think changing your config to a named location ("@foo") changes anything. What did you mean by "comneting and restarting". Restarting nginx or django?

Do you get any errors when reloading your nginx config?

Did you check, whether you really get a 404 when your django project is down? I have a proxy_pass in my config to proxy a webcam. When this webcam is unavailable, I get a "502 Bad Gateway".

If I catch it with error_page 502 /error_page.html; and

        location = /error_page.html  {
             root /what/ever/folder;
    }

my custom error file gets served.

3
  • By logic yes, it should be simple, but I've tried that and nothing. After that I found another thing that I'm currently testing, that I'm gonna explain.
    – Madox
    Apr 15, 2016 at 6:31
  • So you created /usr/share/nginx/html and put error_page.html or custom_404 into it? Apr 15, 2016 at 10:16
  • Ok, so I'll answear one at a time: by "comneting and restarting" -- I mean nginx, django is always stop (for now). I didn't get any error while reloading nginx (I alwways do a configtest) and in the error and access log I didn't see anything odd.
    – Madox
    Apr 18, 2016 at 11:15
1

After talking to a colleague of mine she made me change the way I was handling the issue.

What I wanted was to show a maintenance page, whenever I need to stop/restart the django project so that it won't show a 404 Not Found, because it should a 503 Service temporally unavailable.

So the way I'm currently doing this is by adding the following code:

location / {
    proxy_pass  http://localhost:8000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 60;

    proxy_intercept_errors on;

    error_page 404 = @custom_error;
}

location @custom_error {
    index error_page.html;
    root /usr/share/nginx/www; 
    internal;
}

But this gives me a 502 Bad Gateway, and by comneting and restarting I found that the line that gives me this error is the following line:

error_page 404 = @custom_error;

Maybe I'm doing this the wrong way, but it make sense (to me) that it has to do something with the proxy and this has to detect if service is unavailable on the other end (port 8000).

I've tried the solution that @JosefScript commented above but with no luck.

Another thing I'm thinking is that this version of nginx (1.2.1) has some issues, but I can't update it because the google-cloud-machine works on a modified debian image. And that image has it's own repositories that google manages directly.

1

Thanks to JosefScript's help I could get it done, and here's the final code.

error_page   503 504 500 /50x.html;
error_page   502  /error_page.html;  # NEW 

location /50x.html {
    internal;
    }

location /error_page.html{  #  NEW
    root /home/jumbo;       #  NEW
    }                       #  NEW

location / {
    proxy_pass  http://localhost:8000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 60;

    proxy_intercept_errors on;   #  NEW
    }

What I was doing wrong, I think, is that I didn't tell the 502 error to serve a specific file (my error page) and was waiting for the 404 to serve that file.

Another thing to point out is that I was thinking it all like static file route not a proxy redirect.

Thanks again to @JosefScript for all the help and asking the right questions ^_^

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .