1. The problem I’m having:
I am using caddy on macos with tailscale and several self hosted apps. My setup is working fine but my caddyfile is very repetitive. I include full background below but it may not be relevant. My exact situation is complex but I am mostly looking for some documentation anyone can point me to on whether caddyfiles can define policies centrally and refer to them as needed.
I want each app to be available in 2 ways:
- Through my tailscale url and that app’s port number eg
https://machinename.tailnetname.ts.net:1234
- Through an app-specific subdomain of my personal domain
https://appname.example.com
I also want to use forward auth with Authentik for each app. I set up Authentik on ports 9001/9444 and reverse proxy with
# Authentik
machinename.tailnetname.ts.net:9001 {
reverse_proxy :9000
}
machinename.tailnetname.ts.net:9444 {
reverse_proxy :9443
}
I also want each app to have https. For the tailscale url (ending ts.net
), caddy gets the certs from tailscale automatically but for my personal domain (example.com
) I need to use a dns plugin as the tailscale 100.x IP address the domain points to is not publicly routable.
As tailscale is listening on port 443 I cannot bind to it and I configured tailscale to forward to 444 instead, which is where my caddy listens below.
For each app I have the following in my caddyfile (this particular app is natively on port 3000 of the machine and is named ‘app’ and so should be available at https://machinename.tailnetname.ts.net:3000
and https://app.example.com
):
machinename.tailnetname.ts.net:3000 {
# always forward outpost path to actual outpost
reverse_proxy /outpost.goauthentik.io/* https://machinename.tailnetname.ts.net:9001
# forward authentication to outpost
forward_auth https://machinename.tailnetname.ts.net:9001 {
uri /outpost.goauthentik.io/auth/caddy
# capitalization of the headers is important, otherwise they will be empty
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
# optional, in this config trust all private ranges, should probably be set to the outposts IP
trusted_proxies private_ranges
}
reverse_proxy :3000
}
app.example.com:444 {
# always forward outpost path to actual outpost
reverse_proxy /outpost.goauthentik.io/* https://machinename.tailnetname.ts.net:9001
# forward authentication to outpost
forward_auth https://machinename.tailnetname.ts.net:9001 {
uri /outpost.goauthentik.io/auth/caddy
# capitalization of the headers is important, otherwise they will be empty
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
# optional, in this config trust all private ranges, should probably be set to the outposts IP
trusted_proxies private_ranges
}
tls {
dns route53 {
access_key_id "..."
secret_access_key "..."
}
}
reverse_proxy :3000
}
This is very repetitive as I need to repeat the entire block, forward auth and all, as I have 2 different tls methods for the 2 hostnames. I then need to repeat the entire thing for each app.
Is there any way to define tls and forward_auth policies in one place and refer to them as needed?
Thank you.
2. Error messages and/or full log output:
n/a - everything is working fine
3. Caddy version:
4. How I installed and ran Caddy:
a. System environment:
macos, caddy v2.6.4 installed using xcaddy with route53 module. Tailscale.
b. Command:
caddy
c. Service/unit/compose file:
see above
d. My complete Caddy config:
see above