‘redir’ through Caddyserver

3 minute read

When I moved my website from Github Pages to my own server, I had some problems and unanswered questions regarding automatic redirects. My blog migrated from the root domain to a subdomain (blog.schallbert.de).

Requirements for the redirect

  • Links already referencing to my blog articles under the old name, e.g. to schallbert.de/about should redirect correctly to the subdomain (no 404)
  • The root page under schallbert.de should be fully usable
  • Data and files for domain and subdomains should be independent of each other
  • The web servers should be able to use different technologies for different subpages

Implementation

At first I had thought that I could achieve the redirects in the DNS provider via A and CNAME entries. However, I quickly realized that a) I had no idea how DNS even works and b) the right way is via the configuration of my web server.

First attempt: redir at ‘/’

On my web server (Caddy), redirects are specified in the Caddyfile via redir. This can be done permanently (as so-called http 301) or temporarily via 302. Default is a temporary redirect.

My first thought was to leave schallbert.de unmodified and forward everything after a possible /. This would then look like this in the Caddyfile:

schallbert.de {
        # Define webserver
        root * /www/landing
        encode gzip
        file_server

        # Redir to subdomain if domain has a slash
        @redirect path_regexp /*
        redir @redirect https://blog.schallbert.de{uri}
}

As a result, Caddy simply forwarded everything to the subdomain. The catch was that the subdomain itself also contains slashes or a URI after the slash and is then forwarded yet again. Example:

schallbert.de/post -> blog.schallbert.de/post -> blog.schallbert.de/post -> blog.schallbert.de/post -> [...]

This gave me a recursive endless redirect. I completely paralyzed my server with it 😅

Second attempt: Filtering via regexp

I need better filtering so that only slashes with additional characters behind them are actually redirected and the forwarding cannot be recursive. Fortunately, I had help from a good friend, so that the following Caddyfile was created a short time later:

schallbert.de {
        # Define webserver
        root * /www/landing
        encode gzip
        file_server

        # Redir to subdomain to maintain links for blog
        @redirect path_regexp ^/[^/]+(/.*)?$
        redir @redirect https://blog.schallbert.de{uri}
}

The Regexp checks whether there is a slash after the domain URL and whether it is followed by at least one other character. The redirection now works as desired and my blog is still fully accessible under the old links.

Nevertheless, I was still not completely satisfied. Because when I created a nice “landing page” on my root domain, suddenly only the plain HTML was visible. No favicon, no images, no CSS.

A quick look at the developer options quickly brought the realization that paths of all assets that I had stored on my landing page, marked with / in the folder structure, were forwarded to the subdomain. Where they are not located, of course.

Fortunately, I’m not alone with this problem, so I found the solution in Caddy’s forum:

With the not file marker I can define redirects in Caddyfile if resources on the current page cannot be found.

My solution now looks like this:

schallbert.de {
        @filenotfound {
          path_regexp ^/[^/]+(/.*)?$
          not file
        }

        # show Caddy where to find page resources
        root * /www/landing
        encode gzip

        route {
          # Redirect to subdomain if article cannot found on root
          redir @filenotfound https://blog.schallbert.de{uri}

          # else, define webserver and show page
          file_server
        }
}

Here it is important to define the page with root * /www/<pagelocation> before creating the route. Otherwise the assets will only become available after I have already forwarded them for lack of existing files.

Success!

Now my construction site page is finally displayed correctly.

Image: Correctly rendered 'website under construction' page on schallbert.de