Use `tls.get_certificate` only for specific domains

Summary

I’d like to use tls.get_certificate function only for specific domains, while keeping the automatic HTTPS feature for other domains and Caddyfile format.

I need to manage the same certificate in multiple instances (not only Caddy). For example, I need to get the certificate of domain.tld and use it in multiple servers. The servers can be other types of TLS hosts aside from Caddy.

Caddy and system environment

Caddy compiled via: xcaddy build --with github.com/mastercactapus/proxyprotocol with go1.21.3 is running on: the debian/bullseye (11) container in LXD host.

  • v2.7.5 h1:HoysvZkLcN2xJExEepaFHK92Qgs7xAiCFydN5x5Hs6Q=
  • debian/bullseye (11)

Failed workarounds

I tried to build a certificate server powered by dehydrated.sh and distribute the certificate via http host. Then, I set the tls.get_certificate config in Caddyfile:

{
	servers {
		listener_wrappers {
			proxy_protocol {
				timeout 2s
				allow 0.0.0.0/0
			}
			tls
		}
	}
}

domain.tld {
  tls {
    get_certificate http https://certificate_server/path/to/certificate.pem
  }
}

otherdomain.tld {
  reverse_proxy * internal-host:80
}

In this case, I thought Caddy should obtain the certificate from certificate_server even they’re registered in automatic certificate management.

They did.

* Added domain.tld:443:x.x.x.x to DNS cache
* Hostname domain.tld was found in DNS cache
*   Trying x.x.x.x:443...
* Connected to domain.tld (x.x.x.x) port 443 (#0)
* ALPN: offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=domain.tld
*  start date: Oct 12 05:37:54 2023 GMT
*  expire date: Jan 10 05:37:53 2024 GMT
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* using HTTP/2
* h2 [:method: GET]
* h2 [:scheme: https]
* h2 [:authority: domain.tld]
* h2 [:path: /]
* h2 [user-agent: curl/8.1.2]
* h2 [accept: */*]
* Using Stream ID: 1 (easy handle 0x120014c00)
> GET / HTTP/2
> Host: domain.tld
> User-Agent: curl/8.1.2
> Accept: */*
> 
< HTTP/2 302 
HTTP/2 302 
< alt-svc: h3=":443"; ma=2592000
alt-svc: h3=":443"; ma=2592000
< location: https://anotherlocation.domain.tld
location: https://anotherlocation.domain.tld
< server: Caddy
server: Caddy
< content-length: 0
content-length: 0
< date: Sat, 14 Oct 2023 14:03:46 GMT
date: Sat, 14 Oct 2023 14:03:46 GMT

< 
* Connection #0 to host domain.tld left intact

However, the problem is that they served the certificate in other domains too. This means Caddy served the certificate from the certificate server defined in tls.get_certificate instead of using acme.

130 % curl https://otherdomain.tld                                                                                                                                                  
curl: (60) SSL: no alternative certificate subject name matches target host name 'otherdomain.tld'
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Actually it looks like there’s a Caddyfile adapter bug here.

If you run caddy adapt -p -c Caddyfile you’ll see that your get_certificate is missing. If you comment out the otherdomain.tld site block, then get_certificate reappears.

For now you might need to write the JSON config you need until we have it fixed. You’ll need to make sure you have more than one automation policy in the config, one for the domains you want get_certificate for, and another for the rest you want to automate.

2 Likes

I got a fix:

2 Likes

I’d like to help to fix the issue but not able to code in golang at this time. Thank you so much for both fast response and kind suggestions.

1 Like

No worries, it is fixed in the PR above, and already merged. It’ll land in the next release. For now you can build Caddy from the master branch to use it.

2 Likes

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