Redirect root to www virtual host and provision certs on demand

1. Caddy version (caddy version):

2.2.1

2. How I run Caddy:

sudo service caddy start

a. System environment:

Debian 10

b. Command:

N/A

c. Service/unit/compose file:

N/A

d. My complete Caddyfile or JSON config:

{
    tls_on_demand {
        ask localhost
    }
}

:80 {
    redir https://www.{host}{uri}
}

:443 {
    tls tls@example.com { on_demand }
    reverse_proxy localhost:8080
}

3. The problem I’m having:

Trying to redirect root to www for all virtual hosts generically and provision certs on demand

What’s the actual problem though? Please be more specific. What’s in your logs? What are the symptoms?

The sites don’t load and no certs are requested. This is all I could see in the logs:

Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.5085702,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adap
ter":""}
Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.5106173,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforc
e_origin":false,"origins":["localhost:2019","[::1]:2019","127.0.0.1:2019"]}
Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.5111353,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic HTTP
S will be applied to this server","server_name":"srv0","http_port":80}
Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.5114248,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS conne
ction policies; adding one to enable TLS","server_name":"srv1","https_port":443}
Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.511695,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv1"}
Nov 23 20:51:15 web caddy[10459]: {"level":"warn","ts":1606182675.5119667,"logger":"http","msg":"user server is listening on same interface as automatic HTTP->H
TTPS redirects; user-configured routes might override these redirects","server_name":"srv0","interface":"tcp/:80"}
Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.5112581,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","c
ache":"0xc000373490"}
Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.5130527,"msg":"autosaved config","file":"/var/lib/caddy/.config/caddy/autosave.json"}
Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.5133226,"msg":"serving initial configuration"}
Nov 23 20:51:15 web caddy[10459]: {"level":"info","ts":1606182675.5130901,"logger":"tls","msg":"cleaned up storage units"}

I’m basically trying to do this, except I don’t know the domains ahead of time:

example.com {
    redir https://www.{host}{uri}
}
https://www.example.com {
    reverse_proxy localhost:7777
}

Regardless of my particular setup, how do people typically go about setting this up?

Thank you!

Well, you got the global option name wrong, it’s on_demand_tls

Also you must use newlines for blocks in the Caddyfile (i.e. hit enter after {)

tls tls@example.com {
	on_demand
}

I see nothing wrong in your logs.

This is extremely vague. Please be more specific. What exactly are you seeing?

Sorry, I goofed when copy/pasting from notes. Those errors were not present in my file. It currently looks like this:

{
    on_demand_tls {
        ask IP
    }
}

:80 {
    redir https://www.{host}{uri}
}

:443 {
    tls tls@example.com {
        on_demand
    }
    reverse_proxy IP:7777
}

Issuing a request to a domain gives the following result:

curl -vL --head http://francecyclingtours.com
* Rebuilt URL to: http://francecyclingtours.com/
*   Trying 192.155.90.186...
* TCP_NODELAY set
* Connected to francecyclingtours.com (192.155.90.186) port 80 (#0)
> HEAD / HTTP/1.1
> Host: francecyclingtours.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 302 Found
HTTP/1.1 302 Found
< Location: https://www.francecyclingtours.com/
Location: https://www.francecyclingtours.com/
< Server: Caddy
Server: Caddy
< Date: Wed, 25 Nov 2020 02:22:47 GMT
Date: Wed, 25 Nov 2020 02:22:47 GMT

<
* Connection #0 to host francecyclingtours.com left intact
* Issue another request to this URL: 'https://www.francecyclingtours.com/'
*   Trying 192.155.90.186...
* TCP_NODELAY set
* Connected to www.francecyclingtours.com (192.155.90.186) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS alert, Server hello (2):
* error:14004438:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert internal error
* stopped the pause stream!
* Closing connection 1
curl: (35) error:14004438:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert internal error

If you add the debug global option (just before on_demand_tls) and try again, is there anything new in the logs?

Thank you, thank you, thank you! I was able to figure it out with the debug info.

I wasn’t thinking that the ask endpoint would pass through Caddy as well, so it was trying to ask https://www.localhost for domain approval.

I put the ask service on another port to get around it. Working config looks more like this:

{
    on_demand_tls {
        ask http://localhost:7777
    }
}

:80 {
    https://www.{host}{uri}
}

:443 {
    tls web@example.com {
        on_demand
    }
    reverse_proxy localhost:7777
}

Thanks again!

1 Like

By the way, doing ask that way opens you up to abuse. Someone could DDOS your server very easily by making requests with a different hostname every time to continually make your server issue new certificates. This might make you hit rate limits, or worse, fill your filesystem with tons of useless certificates until you run out of space.

You should be ask-ing an endpoint that will actually tell you whether the given domain is part of some known list (from your database or whatever).

Thanks for the tip! I’m going to check against a fixed list.

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