1. The problem I’m having:
I’m working on a service that’s supposed to serve websites for dozens/hundreds of domains and subdomains, using on-demand SSL to make the whole setup simpler. I want to keep the config file as generic as possible, so I don’t want to create a config entry for every domain/subdomain we host. I want to just tell a client to redirect their domain/subdomain/www to my IP and their website should magically work.
To make it simple:
- Some websites will run on subdomains (ex,
products.customer.com
) - Some websites will run on the apex domain (ex,
customer.com
) and these will need a redirect towww.customer.com
I need to be able to detect whether the hostname of a request is a naked/apex domain (customer.com
) or if it is a subdomain from a domain (products.customer.com
). I thought of using regexes on {host}
but TLDs can vary a lot (foo.com
, foo.co.uk
, foo.travel
, etc - there are 1,502 TLDs right now). Can’t use {labels}
either for the same reason.
The logic I need is:
- If the request is for a subdomain (and the subdomain is not “www.”), I serve it.
- If the request is for a “www.” subdomain (easy to detect, just check whether
{host}
begins withwww.
), I serve it. - If the request is for a naked/apex domain without subdomains, I redirect to “www.{host}{uri}”.
It would be easy to manually create configs for each individual domain/subdomain case, but I wanted to avoid that and have a very generic config file that I’ll never have to touch again (lol).
How can I express that?
One thought I had was to extend Caddy to support a new placeholder {domain}
({http.request.domain}
) in addition to {host}
, where {domain}
is parsed by github.com/weppos/publicsuffix-go
and would represent just the domain part of {host}
regardless of TLD (assuming it’s not an IP, etc).
Then I can just check whether {host}
equals {domain}
, and if true, that means I’m serving the naked/apex domain (so I can redirect to www.{host}{uri}
).
Is there already a way to achieve what I need without having to mod Caddy?
Thanks!
Caddy version:
v2.7.6
My complete Caddy config:
(logger) {
log {
format json
# output file /logs/{args[0]}-{args[1]}.log {
output file /logs/{args[0]}.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
}
{
servers {
max_header_size 4kb
timeouts {
read_body 10s
read_header 10s
write 10s
idle 1m
}
}
on_demand_tls {
ask https://127.0.0.1/validate-domain
interval 1s
burst 5
}
debug
storage file_system /var/lib/caddy/storage
persist_config off
log {
format json
level DEBUG
output file /logs/caddy.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
}
:443 {
import logger webengine
tls dansouza@mail.io {
resolvers 8.8.8.8 8.8.4.4
on_demand
}
encode gzip zstd
root * /www/webengine/webengine-root
@static_files {
path *.gif *.jpg *.jpeg *.png *.js *.css *.eot *.ttf *.woff *.woff2
}
route @static_files {
file_server
}
php_fastcgi unix///run/php/php8.1-fpm.sock {
env CONFIG_NAME cluster-production
root /www/webengine/webengine-root
try_files /index.php
index index.php
}
}