Create a custom 410 error page in NGINX

When converting this blog from WordPress to Pelican I decided I just ditch a whole bunch of articles I had written in WordPress. According to several articles on the net it is best practice to have pages you delete return a 410 page. For a better user experience I wanted used to land on a page that looks like part of the blog.

As I’m using NGINX you can utilize the map function to create a new variable whose value depends on values of one or more of the source variables specified in the first parameter. I created a file called old_request.nginx in the directory /etc/nginx/snippets/

map $request_uri $gone_var {
  /the-avh-amazon-plugin-has-reached-its-end-of-life/ 1;
  /wordpress-plugin-update-avh-first-defense-against-spam-v3-0/ 1;
  /end-of-the-avh-amazon-plugin/ 1;
  /wordpress-plugin-update-avh-extended-categories/ 1;
}

This file just needs to be included in your configuration file, and if you want to have a custom 410 error page you just have to tell NGINX which file to use when it encounters a 410 error.

include snippets/old_request.nginx;

server {
    ....

    error_page 404 /404.html;
    error_page 410 /410.html;

    if ($gone_var) {
        return 410;
    }

    location / {
        ....
    }
}

Easy enough, NOT. The above configuration does not work. If you try to browse one of the URLs mentioned in the the old_request.nginx file you get the default NGINX 410 error page and not the file you said it should show.

To fix this we have to use a named location. A named location has the @ prefix. Such a location is not used for a regular request processing, but instead used for request redirection.

include snippets/old_request.nginx;

server {
    ....

    error_page 404 /404.html;
    error_page 410 @gone;

    if ($gone_var) {
        return 410;
    }

    location @gone {
        rewrite ^(.*)$ /410.html break;
    }

    location / {
        ....
    }
}

And now your custom 410 error page works.