Well hello again. Another post you say? Another pointless post you may be thinking. Let's see...

Currently this site and others under swakes.co.uk and swakes.uk are being managed and rendered to you via NGINX. As standard, NGINX comes with some pretty boring and basic error pages to handle 403, 404, 503 etc error codes. However we can change that and at the same time do some clever scheming to add some security, if not obscurity, to your pages.

The plan? To present a 404 error page for any error response page generated. The reason? If anyone attempts to access a restricted site (managed by local.conf) they would expect to see a '403 Access Forbidden' but in this case, we can present a 404 'Not Found' page instead, hopefully deterring any further attempts! Of course this won't be able to mask the true 403, 503 etc response in your browsers network tab or logs but at least it's something!

If you've got past the ramblings above and still reading this, I'll assume that you too have a NGINX web server setup and want to setup some error pages! If not, check out my previous post here as you'll definitely need a NGINX web server to continue.

So where to begin? Two parts to this. The error.conf NGINX snippet and the custom HTML error page. Let's start with the snippet.

Error.conf

First we'll need to create the error configuration snippet:

sudo nano /etc/nginx/snippets/error.conf
# Configuration Snippet File: /etc/nginx/snippets/error.conf:

	error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 500 501 502 503 504 505 506 507 508 509 510 511 /HTTP404.html; 
    
	location = /HTTP404.html {
		root /var/www/error; 
}
	location = /error.png {
  		root /var/www/error;
}
	location = /error.css {
  		root /var/www/error;
}

You might be able to guess what's going on within the snippet. Any and all error responses will ultimately serve up our 404 error page with the locations of the HTML, image and CSS files below.

Now the second part, the custom HTML page. Begin with creating a new error folder alongside your other sites in /var/www/

sudo mkdir /var/www/error

So the next step is to create the page! At this point its comes down to your decision, theming etc but for now we'll have a ganders at what I've managed to cobble together using HTML and Animate.css.

Image

You'll need an image to use for the animation in this setup. Any temporary image for now if you haven't got anything in mine. Also try and save the file with reasonable dimensions to avoid any stretching etc. Save the file in the /var/www/error folder ensuring you use the same filename/extension in your configuration.

HTML

sudo nano /var/www/error/HTTP404.html

Creating a plain HTML page would be too simple so to mix it up so included is the Animate CSS library, allowing you to add animations to static image or assets. In this case I've used a hinged effect on my image, added a delay and slowed it down a tad ...class="animated hinge delay-3s slow".

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>Opps looks like a 404...</title>
<link rel="stylesheet" href="error.css">
</head>

<body style="background-color:#13274B;">
<img width="436" height="243" class="animated hinge delay-3s slow" src="error.png"/>
</body>

</html>

If you're a wizard or know your way around HTML/CSS then you probably don't need me to explain what to change etc, however if you want a quick and easy setup, change the following from the above:

<title>Opps looks like a 404...</title>
The title of the page.
<body style="background-color:#13274B;">
The background colour of the page. Currently 'SWAKES Bleu'
<img width="436" height="243" class="animated hinge delay-3s slow" src="error.png"/>
This defines the image (size and location) and which animation to apply (type, delay and speed).

CSS

sudo nano /var/www/error/error.css

As we are using the hinge animation, I've snipped out the remaining irrelevant lines from the CSS library (3634 lines down to 171) however if you want to use a different animation, you can do the same and snip out the crap or keep the full CSS file. Full CSS file available here.

img {
  max-height: 100%;
  max-width: 100%;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}

@charset "UTF-8";

/*!
 * animate.css -http://daneden.me/animate
 * Version - 3.7.0
 * Licensed under the MIT license - http://opensource.org/licenses/MIT
 *
 * Copyright (c) 2018 Daniel Eden
 */

@-webkit-keyframes hinge {
  0% {
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }

  20%,
  60% {
    -webkit-transform: rotate3d(0, 0, 1, 80deg);
    transform: rotate3d(0, 0, 1, 80deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }

  40%,
  80% {
    -webkit-transform: rotate3d(0, 0, 1, 60deg);
    transform: rotate3d(0, 0, 1, 60deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
    opacity: 1;
  }

  to {
    -webkit-transform: translate3d(0, 700px, 0);
    transform: translate3d(0, 700px, 0);
    opacity: 0;
  }
}

@keyframes hinge {
  0% {
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }

  20%,
  60% {
    -webkit-transform: rotate3d(0, 0, 1, 80deg);
    transform: rotate3d(0, 0, 1, 80deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }

  40%,
  80% {
    -webkit-transform: rotate3d(0, 0, 1, 60deg);
    transform: rotate3d(0, 0, 1, 60deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
    opacity: 1;
  }

  to {
    -webkit-transform: translate3d(0, 700px, 0);
    transform: translate3d(0, 700px, 0);
    opacity: 0;
  }
}

.hinge {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
  -webkit-animation-name: hinge;
  animation-name: hinge;
}


.slideOutUp {
  -webkit-animation-name: slideOutUp;
  animation-name: slideOutUp;
}

.animated {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}

.animated.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}

.animated.delay-1s {
  -webkit-animation-delay: 1s;
  animation-delay: 1s;
}

.animated.delay-2s {
  -webkit-animation-delay: 2s;
  animation-delay: 2s;
}

.animated.delay-3s {
  -webkit-animation-delay: 3s;
  animation-delay: 3s;
}

.animated.delay-4s {
  -webkit-animation-delay: 4s;
  animation-delay: 4s;
}

.animated.delay-5s {
  -webkit-animation-delay: 5s;
  animation-delay: 5s;
}

.animated.fast {
  -webkit-animation-duration: 800ms;
  animation-duration: 800ms;
}

.animated.faster {
  -webkit-animation-duration: 500ms;
  animation-duration: 500ms;
}

.animated.slow {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
}

.animated.slower {
  -webkit-animation-duration: 3s;
  animation-duration: 3s;
}

@media (prefers-reduced-motion) {
  .animated {
    -webkit-animation: unset !important;
    animation: unset !important;
    -webkit-transition: none !important;
    transition: none !important;
  }
}

Good stuff. We should have everything setup and ready to implement!

To apply the new error page config to your site, simply include the line in configuration file:

include /etc/nginx/snippets/error.conf;

All done!. An easy way to test? If you've got a local.conf (IP list access - check out previous post if you haven't already!), setup one of your sites to be 'local' only access then attempt to visit it via a different network (3/4G, VPN). If I've wrote this correctly and coherently then you should be seeing your new shiny error page!