skip to content

Configuring Caddy to route to custom 404-page

/ 2 min read

UPDATE Apparently, this was only necessary for my site, when it was built with Hexo. I have migrated to Astro, which handles the routing for me now.

Often overlooked, yet helpful: it is nice-to-have a proper 404-page, of which some are humorous. All of them serve a better browsing experience, because that page tells the user that a requested resource (page) does not exist. Without a 404-page, the browser would just display a blank page, which is not helpful.

In order have offer this on the own website, there are two requirements:

  1. there must be a html-file that serves as 404-page
  2. the error-handling or routing of the web server must be configured, so requests for non-existent resources are properly handled, in this case: forwarded to the custom 404-page.

Updating your Caddyfile

The following text focuses on the second point, using Caddy as web server.

  1. Open your Caddyfile in an editor
  2. Add the handle_errors-snippet:
Caddyfile {
root * /path/to/your/sites/directory # location of your build artifact
file_server # enable the static file server
handle_errors { # set up error handlers
rewrite * /{err.status_code}.html # rewrite requests internally, `*` matching all failed requests
file_server # preserve the error's HTTP status code when run in handle_errors
  1. Reload the configuration, e.g. via sudo systemctl reload caddy

Additional resources

  • Original source with Caddyfile configuration, I was using at first
  • Official documentation on handle_errors. Check out the examples! Seeing this also makes me realise how unnecessary this post is. I am going to post this text nevertheless, as reference to my future self.
  • Official documentation on rewrite directive


The following snippet is the configuration I had used until recently. Writing this article, I was about to use that snippet (see below). This time, I also checked out the referenced issue and realised that the official documentation now offers a much simpler and more flexible configuration.

Caddyfile (outdated config) {
root * /path/to/your/sites/directory
handle_errors {
@404 {
expression {http.error.status_code} == 404
rewrite @404 /404.html