A few questions after migrating to Caddy from Hiawatha

Salutations all.

I’m trying to see if I can get functionality similar to Hiawatha with an easier setup with Caddy. I’ve run into two roadblocks at the moment though, and I’m not sure if I’m missing a feature / misunderstanding the settings or if Caddy simply cannot do it.


The first thing, since I imagine it’s simpler, is redirection. Using Hiawatha, I had a redirect that would pull you to a portal site if you typed in an improper address. Basically, I had it all setup so it was www.example.com, site1.example.com, site2.example.com, etc. If you accidentily typed in stie2.example com ( so you misspelled the subdomain but the domain was the same ) you would get redirected automatically to www, which then provides a map for you to get where you want to go. Caddy does this just fine for http:

http://*.example.com {
        redir 301 {
                / https://www.example.com
        }
}

Any website not explicitly defined gets redirected to www. So stie2 goes to www but site2 would go to site2. Perfect. Almost. If you type in https://stie2.example.com though, you wind up with a certificate error and Caddy responding with No such site at :443

Is there a way to make Caddy respond similarly in both cases?


The second thing. I’m having issues with timeouts / proxies. I looked through the doc files but I don’t see an option to apply a timeout setting only to a proxy. The timeouts directive appears to be server wide. If I go with the defaults and, for example, reverse proxy a RocketChat instance, the instance works okay but ever 10 seconds the page reloads because the websocket is reset. Change the timeout setting, and it resets whenever you set the timeout to. For now I have timeouts none which works ( specifically atm for RocketChat and Wetty ) but it’d be nice if there was a better / more secure way to go about this. In Hiawatha I would specify long timeouts on the reverse proxy connection itself, but I don’t see a way to do this in Caddy based on the docs.

Examples - Hiawatha ( long proxy timeout only )

VirtualHost {
	Hostname = chat.example.com
	WebSocket = ws://192.168.0.51:3000 /sockjs/(.*)/websocket 3600
	ReverseProxy .* http://192.168.0.51:3000 3600
	WebsiteRoot = /srv/empty
	RequireTLS = yes
}

Examples - Caddy ( timeouts none )

https://chat.example.com {
        proxy / 192.168.0.51:3000 {
                transparent
                websocket
        }
        root /etc/caddy/blank
        timeouts none
}

Thanks in advance for any help.

From a theoretical standpoint, this problem is much more difficult to solve than a simple wildcard redirection.

Caddy doesn’t actually have a certificate for the misspelled subdomain, so in order to honour the HTTPS connection request, it must present the first available certificate. If the certificate mismatch is ignored by the client, Caddy sends the “No such site” error as no vhost has been configured to tell Caddy how to serve this request.

However, Caddy’s on-demand TLS feature might be able to solve this for you. Instead of the HTTP wildcard redirect, you would instead use something like this:

*.example.com {
    redir 301 {
        / https://www.example.com
    }
    tls {
        max_certs 10
    }
}
  • Takes HTTPS wildcard requests and requisitions a certificate for them on the fly, up to 10 times
  • Serves unknown subdomains on both protocols with redirects to the www subdomain via HTTPS

Downside - once 10 certs have been requisitioned, it will start presenting invalid certificates again (but the redirection will work if the error is ignored by the client). You can tweak this number, but the hard limit from LetsEncrypt is 20 total per week, and you’ll probably want some wiggle room for the actual domains you want to serve (like www) which will cut into that total.


Unfortunately I don’t have a good answer for your timeouts question, sorry.

1 Like

I understand the timeouts can be a little frustrating. At least we have them now, we didn’t before. We’re waiting for the Go standard library to expose a way to do timeouts per-request, but the timeouts are handled at a lower (listener) level, before the HTTP headers are received… so either we need to wait for Go standard lib to support this or I’m missing something (feel free to point me in the right direction!) – but this is what we have for now.

1 Like

Hm. I’ll make the changes above; in my Hiawatha config I was using a PositiveSSL wildcard cert and was hoping to move off the due to the expense but it might be cheaper config / use wise to keep provisioning it.

I tried to setup a double proxy just to test to see if I could get around the delay / timeout problem with Rocket.Chat by having the RC host use a caddy on the default port with no timeouts proxied locally to RC, and then the ‘main’ server caddy where the SSL would be requested proxying to the downstream caddy. Unfortunately that didn’t work; again I could utilise the timeouts none Caddy with no reloads but the “main” Caddy which had timeouts enabled still worked the same way even talking to another Caddy server.

I’m not a Go expert but maybe that’s a potential workaround point. Having Caddy trust itself so that if the listener was port 2015 ( or some other specific port named in docs ) it didn’t use the timeouts but any other port would? It’d likely have to be hard coded but one would expect port 2015 to only be used in a local environment and not generally be the ‘world open’ one. That would allow you a scenario ( Caddy → Caddy → Service [ on any port ] or Caddy → Service [ with said specific defined port ] ) where you could have timeouts for most things? Or is the listener you refer to a different part of the code?

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