Sure! I have all my self-hosted apps running on subdomains under 1 domain. So let's say it's "mydomain.com" and then I have subdomains like "gitlab.mydomain.com". So for this setup I add a block at the top of my Caddyfile:

(secure) {
jwt {
path /
redirect https://auth.mydomain.com/login?backTo=https://{host}{uri}
except /api
except /rest
except /zm/cgi-bin/nph-zms
except /zm/api
}
}

The "except"'s are for some services I use that have some kind of api-based auth for reaching certain endpoints that need to be whitelisted. This approach (of importing this "secure" block in each caddy block, that's just what I called it, "secure" isn't a special word) has the downside of requiring a global list but makes it easier as you will see in just a minute. Also there wasn't any overlap of "services that have api endpoints using api keys" and "services that have the same endpoint but it needs to be under SSO auth". Moving on, after that block I have my "auth" url, again you can name this whatever:

auth.mydomain.com {
login {
simple username=password
jwt_expiry 24h
redirect_check_referer false
redirect_host_file /root/.caddy/hosts
cookie_expiry 2400h
cookie_domain mydomain.com
}
}

The "simple username=password" is the line doing a lot of the heavy lifting but you can replace that with something that uses a different SSO provider (like Google, LDAP, etc). I have a random U/P that I store in 1Password so "simple" is fine for me but I've wanted to setup Google's OAUTH to at least test it out. The other big thing here is "/root/.caddy/hosts", this is a list of all the domains/hosts (one per line) that you want to be able to redirect to. This is so that if you go to "gitlab.mydomain.com" and you aren't logged in it will bounce to auth.mydomain.com and then, because you put "gitlab.mydomain.com" in that "/root/.caddy/hosts" file, it will redirect back to "gitlab.mydomain.com" once you login. Gitlab may be a bad example since you will absolutely be using GL's auth as well but substitute Gitlab with other services that either don't provide auth or provide some basic auth you can turn on/off, that's where this really shines. Once you are logged into 1 of them you are logged into all of them.

Lastly we have our actual, regular, caddy entires: (and looking at mine I see I should have been using Syncthing as the example all along haha)

syncthing.mydomain.com {
import secure
proxy / 10.0.1.123:8384 {
transparent
websocket
}
gzip
tls myname@mydomain.com
}

I will note that you might not need the "websocket" line anymore but it works and I'm not touching it. That "import secure" line is what "protects" the Syncthing service.

It has been a breeze to add/remove services that I want to stick behind auth and I'm very happy with it. A couple caveats: I still need to update to Caddy 2, it came out shortly after I did all this work I decided to sit back and wait for the dust to settle. Also I wasn't able to use the default caddy docker image, it needs some extra plugins. This may no longer be the case for Caddy 2, I don't know. I ended up just making my own image [0] (/Do not use this/, really, don't. I'm not going to keep it updated, I make no promises, and it's a huge security risk IMHO) by forking the repo and adding the extra plugins I needed [1]. You can do the same and build locally or maybe you don't even use docker and so this is a non-issue. The two plugins I needed were "jwt" and "login".

I hope this helps and I can answer any other questions you might have about it.

[0] https://hub.docker.com/r/joshstrange/caddy

[1] https://github.com/joshstrange/caddy-docker/blob/master/Dock...