How to redirect all www.* to *?

1. The problem I’m having:

Hello, I am running a multi-tenant application with Caddy handling traffic via on-demand TLS. I would like to permanently redirect all requests coming from www.* subdomains to their host domain.

So for example:

  1. www.example.com —301–> example.com
  2. www.any-domain.com —301–> any-domain.com
  3. www.* —301–> * (something like this)

Here is my current Caddyfile configuration (with comments added only here for clarity):

# Checks if caddy is allowed to issue a certificate for the requested domain
{
  on_demand_tls {
    ask http://app:3000/api/caddy/check-domain
  }
  email {$CADDY_EMAIL}
}

# Redirects all non secure traffic to HTTPS
:80 {
  redir https://{host}{uri} permanent
}

# Issues a certificate for the requested domain based on on-demand TLS,
# Reverse proxies the request to a next.js app serving websites for multiple tenants
:443 {
  tls {
    on_demand
  }

  reverse_proxy app:3000
}

I cannot hard-code something like the example below because adding a new rule every time a new tenant adds his domain to my platform would be tedious. There surely has to be a more elegant solution similar to on-demand TLS magic from above.

# This will not work since I need a solution that works for all domains
www.example.com {
  redir example.com permanent
}

# Is something like this possible to do?
www.* {
  redir * permanent
}

If you have any ideas or hints that might get me on the right track please let me know I would appreciate it very much. Thank you :folded_hands:

2. Caddy version:

caddy:2.10.2-alpine - via docker compose

See if host labels would work for you. Here’s an example:

Sorry, I was posting from my phone last time, so I just shared a link to see if it could help.

For what you’re trying to do, I think a simple header_regexp would be a better fit. This is a working example on my laptop, so no TLS or HTTPS here, but you can adjust it to your needs:

Caddyfile:

:80 {

	@www header_regexp www Host ^www\.(.*)$
	redir @www http://{re.www.1} 308

	respond "Alive!"
}

Test:

/etc/hosts:

127.0.0.1 www.example.com example.com www.sub.example.com sub.example.com
$ curl www.example.com -I
HTTP/1.1 308 Permanent Redirect
Location: http://example.com
Server: Caddy
Date: Thu, 16 Oct 2025 17:52:38 GMT

$ curl example.com
Alive!

$ curl www.sub.example.com -I
HTTP/1.1 308 Permanent Redirect
Location: http://sub.example.com
Server: Caddy
Date: Thu, 16 Oct 2025 17:52:54 GMT

$ curl sub.example.com
Alive!

In your case, I’d probably go with something like this:

{
	on_demand_tls {
		ask http://app:3000/api/caddy/check-domain
	}
	email {$CADDY_EMAIL}
	auto_https disable_redirects
}


http:// {
	redir https://{host}{uri} 308
}

https:// {
	tls {
		on_demand
	}

	@www header_regexp www Host ^www\.(.*)$
	redir @www https://{re.www.1} 308

	reverse_proxy app:3000
}

I haven’t tested this version on my laptop, but I believe it should work.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.