How to Add a Custom 404 Error Page to a Cloud Foundry Staticfile Buildpack Site

Replacing the Staticfile Buildpack's Default NGINX 404 Page

September 22, 2017
Default NGINX 404 Page (in all of its glory)

Caution: This gets a bit wordy, so feel free to skip the exposition or reference my example site.

error 404 - configuration options not found

Earlier this week I wrote about how to deploy a static site to Cloud Foundry, and once you’ve familiarized yourself with the basic of Cloud Foundry, it’s pretty darn simple. However, as I migrated one of my sites over from GitLab pages over to Pivotal Web Services I did run into one issue that was particularly annoying: my site was using the default NGINX 404 page and not my lovingly crafted public/404.html.

Now I figured this would be a simple fix. After all, Github pages will serve up a 404.html page automatically and even Amazon S3, despite its byzantine management console, makes it pretty intuitive to set up a “not found” document to serve. So I Googled.

And I didn’t have a whole lot of luck. I did see that you could replace the nginx.conf that the Staticfile buildpack uses to deploy the NGINX server that serves up your static site, so I tried that. I used cf ssh to ssh on to my app and downloaded copied the existing config so that I could append an error_page declaration to it. This wasn’t ideal.

  1. This meant that I would no longer be able to automatically take advantage of improvements that the Staticfile buildpack might make to their nginx.conf in the future
  2. It also meant I had to get a bit too familiar with NGINX config to do something that should have been simple

There had to be an easier way. So I logged an issue to their project to request the ability to set a custom 404 page as a feature. They agreed that it might be valuable, but also let me know of a better way to do what I had already done.

configuring a custom 404 page

Turns out that you can include a location_include directive in your Staticfile (docs). This is a powerful directive that will pull in files specified from your nginx/conf directory and include them in the generate nginx.conf file here. So to get my site to serve my custom 404 page, I did the following:

1. Added an nginx/conf/includes directory to the top-level of my project

2. Added an error404.conf file to the nginx/conf/includes directory that contained the following config:

error_page 404 /404.html;
location = /404.html {
  internal;
}

This tells NGINX to look for a /404.html page within its configured root (_site for my example Jekyll site) that is set by the buildpack at the top of the NGINX location block.

3. Added the following directives to my Staticfile:

root: _site
location_include: includes/*.conf

This config instructs the Staticfile buildpack to set the Jekyll-generated _site folder for the site as root and tells it to include every .conf file within the nginx/conf/includes directory that we created earlier. Make sure you include the root directive since the docs mention that the buildpack requires it be configured alongside location_include for it all to work properly.

After all that, just cf push up your changes and your site should now be serving your custom 404 page instead of that nasty NGINX default.

Again, you can check out my example Jekyll site (tree #e895f96) to see a concrete example of how all of this looks in a real-ish codebase. You can also visit its deployed error page here.

Hopefully this will all be made simpler in the future, but in the meantime, this has been the simplest way I’ve found to add a custom 404 page to a static Cloud Foundry site. Thanks for following along!