July 26th, 2020

Setting up a custom 404 page with Caddy v2

Easy to set up, but not well documented

I wanted a very easy solution for setting up HTTPS so I recently switched my blog from Nginx to Caddy [1].

With Caddy I had HTTPS working in minutes, but I had a little trouble setting up a custom 404 page. This is actually very easy to do in Caddy, but it is very hard to figure it out from the documentation. According to the author of Caddy, Matt Holt, better support for custom error pages will be coming in or after Caddy v2.1.

After reading through some forum posts, and learning more about the Caddyfile format, here is the solution I came up with. You can see it working here.

My Caddyfile

vivekseth.com {
  root * /home/web/blog/public
  file_server
  handle_errors {
    rewrite * /404/index.html
    file_server
  }
}

This tells Caddy to try to serve files from /home/web/blog/public, and to serve <root>/404/index.html whenever it encounters any error.

If you only want to show your 404 page when there is a 404 error, you can use this snippet.

One “Gotcha”

This may seem obvious, but I spent at least 30min trying to debug this issue…

Make sure that the 404 path you use is relative to the “root” you define. For example, since my 404 page is located at /home/web/blog/public/404/index.html, I needed to use /404/index.html as the path. If you use the absolute path to the 404 file, it won’t work.

Hope this helps you set up Caddy with a custom error page!


[1] A few days after I set up Caddy, I ended up learning how to set up HTTPS with Nginx using Lets Encrypt. Its actually very easy and only slightly more work than Caddy. If I did not already have Caddy working, I would probably just continue to use Nginx and use Let’s Encrypt’s certbot to generate and auto-renew my SSL certifcates.