Flatten subdomains by replacing . with _ past .app.example.com

1. The problem I’m having:

I am trying to flatten subdomains to the left of the .app.example.com
to make them look like customerdomain_com.app.example.com and www_customerdomain_com.app.example.com essentially replacing the dots with underscores, allowing a singular wildcard certificate for the *.app.example.com as well as retaining the information needed to direct the request within my application.

So a request would come in looking like www.customerdomain.com.app.example.com and it would be rewritten with the underscores and then redirected and https established at that point.

2. Error messages and/or full log output:

Not currently receiving any errors as I have not identified a method to do this in Caddy just yet. I seen the layer documentation but it did not seem like it was possible to replace the . with _.

3. Caddy version:

v2.7.5 h1:HoysvZkLcN2xJExEepaFHK92Qgs7xAiCFydN5x5Hs6Q=

4. How I installed and ran Caddy:

built with xcaddy with a couple plugins, s3 and route53 currently.

a. System environment:

Ubuntu server 20.04 x86_64 systemd

b. Command:

systemctl start caddy

c. Service/unit/compose file:

d. My complete Caddy config:

Do not really need a config to figure out how to do what I’m asking.

5. Links to relevant resources:

It’s not possible to issue a redirect for an HTTPS connection without having a valid TLS certificate. A redirect happens at the HTTP layer, which is after TLS is established.

You have to fix the problem at the point where those URLs are generated. You need to make sure the URLs have the correct domain to start.

Ignoring the https aspect of this and just focusing on the flattening of the subdomain past the .app.example.com is that possible within Caddy or will it require a plugin or script outside Caddy?

We can sort out the connections and the order in which they are established ourselves, but the domain flattening/rewrite we’re wanting to occur in the http portion of the connection which should allow us to ignore the https issue.

If we could get any help for that flattening component specifically that would be very much appreciated.

It’s possible, but kinda awkward.

@sub header_regexp sub Host ^(.*)\.app\.example\.com$
route @sub {
	request_header X-Subdomain {re.sub.1}
	request_header X-Subdomain \. _
}

Then you can use {header.X-Subdomain} which has just the subdomain with underscores.

But again, I don’t see how this could work because of TLS. Wildcard domains only match a single label (parts between dots) so *.example.com does not match foo.bar.com.example.com. So you’d have to use On Demand TLS, and have a certificate for each individual domain, just to perform redirects. That’s super wasteful.

1 Like

that’s one of our main issues right now that we’re trying to resolve, the fact we have entirely too many certificates for all of those subdomains.

Yeah like I said, that’s something you need to resolve by making whatever produces those URLs to always use underscores instead of dots or whatever. It’s not a resolvable problem otherwise.

@francislavoie Thanks for your replies. Just one more question to be perfectly clear.

There is no option to do any kind of rewriting BEFORE the http → https redirect?

Even if one turned off automatic redirecting?

Yeah, you’d need to turn off the redirects and perform them yourself instead. Set auto_https disable_redirects and then you can use the above config + the placeholder to redir to HTTPS with the fixed domain. Make sure to also have a default redirect for unmatched domains that don’t have that dot issue as well (can be as simple as redir https://{host}{uri} 308 I think)

2 Likes