This was one of those lightbulb moments for me. I had read @matt’s excellent wiki article Composing in the Caddyfile many times over and I’ll continue to read it over and over again I’m sure. There’s so much to take in. Sometimes though, saying things differently can make a world of difference. This was one of those times for me.
I’ve gone through my Caddyfile with a fine-tooth comb reviewing places where I used the handle
directive. I’d like to check off where I’ve replaced this with the route
directive. This will either confirm for me that I understand the differences in these two directives, or, that I still need to reshape and deepen my understanding.
(online) {
@offline expression `"{args.0}" == "no"`
handle @offline {
redir https://udance.statuspage.io temporary
}
@split {
expression `"{args.0}" == "split"`
not remote_ip 10.1.1.0/24 10.1.2.0/24
}
route @split {
redir https://udance.statuspage.io temporary
}
}
In the above snippet, I used the handle
directive with the @offline
matcher because I figured that if there is a match here, I won’t need to run any other handle blocks after this one. On the other hand, I used the route
directive with the @split
matcher. If there’s a match, then for the external network, the redir
is invoked. For the internal network, however, I might still want to fall through to other handle blocks outside this snippet if this snippet happens to be invoked. Is this logic sound?
I applied similar logic to other handle blocks within the wildcard subdomain Caddy block…
*.udance.com.au {
...
map {labels.3} {backend} {online} {mtls} {phpmyadmin} {
# HOSTNAME BACKEND ONLINE mTLS PHPMYADMIN #COMMENT
#---------------------------------------------------------------
...
test test.lan:443 yes yes yes # test.udance.com.au
basil 10.1.1.56:80 yes no yes # basil.udance.com.au
sachika 10.1.1.57:80 yes no yes # sachika.udance.com.au
default unknown yes no no # subdomain does not exist
}
# Error handling
@unknown expression `{backend} == "unknown"`
handle @unknown {
respond "Denied" 403
}
# Site offline
@offline expression `{online} == "no"`
handle @offline {
redir https://udance.statuspage.io temporary
}
@split {
expression `{online} == "split"`
not remote_ip 10.1.1.0/24 10.1.2.0/24
}
route @split {
redir https://udance.statuspage.io temporary
}
# Authenticate phpMyAdmin on production WordPress sites
@phpmyadmin expression `{phpmyadmin} == "yes"`
route @phpmyadmin {
import authorise /phpmyadmin*
}
# Fix when using the Nextcloud+Apache Docker image with Caddy.
@nc-apache host nc-apache.udance.com.au
route @nc-apache {
redir /.well-known/carddav /remote.php/carddav 301
redir /.well-known/caldav /remote.php/caldav 301
}
# Enable HSTS for Nextcloud
@hsts host cloud.udance.com.au
route @hsts {
header {
Strict-Transport-Security max-age=31536000;
}
}
# Secure backend communication
@mtls expression `{mtls} == "yes"`
route @mtls {
reverse_proxy {backend} {
header_up Host {http.reverse_proxy.upstream.hostport}
header_up X-Forwarded-Host {host}
transport http {
tls
}
}
}
# Unsecured backend communication
@nomtls expression `{mtls} == "no"`
route @nomtls {
reverse_proxy {backend}
}
}
...