Mixing wildcard certificate with on_demand feature

1. Caddy version (caddy version): v2.3.0

2. How I run Caddy:

Installation steps:

yum install yum-plugin-copr
yum copr enable @caddy/caddy
yum install caddy

Running in background without systemd and using a Caddyfile

a. System environment:

CentOS 7

b. Command:

caddy start

c. Service/unit/compose file:

Not using right now (dev/poc server)

d. My complete Caddyfile or JSON config:

{
    on_demand_tls {
        ask http://localhost:3000/check
    }
}

*.domain.com, domain.com {
  reverse_proxy localhost:3000
}

:443 {
  reverse_proxy localhost:3000 {
    header_up Host {http.reverse_proxy.upstream.hostport}
    header_up X-Real-IP {http.reverse-proxy.upstream.address}
    header_up X-Forwarded-Port {http.request.port}
    header_up X-Forwarded-Host {http.request.host}
  }

  tls {
    on_demand
  }
}

3. The problem I’m having:

I’m trying to use the (awesome!) on_demand feature because our platform allows users to set their own custom domain (read the serving-tens-of-thousands-of-domains-over-https-with-caddy link post). We also let them use a subdomain too, so they can have user1.domain.com and custom-domain.com.

The custom domain is working properly, getting the certificate at the first request.

My real problem is that caddy didn’t issued a *.domain.com certificate. When someone access userX.domain.com it issues a CN userX.domain.com certificate instead of issuing/using the *.domain.com certificate.

Using the on_demand_tls ask solves the custom certificate for each subdomain (no more CN userX.domain.com certificate) but it didn’t trigger the wildcard certificate and the subdomain gets no issued certificate at all, returning a “This site can’t provide a secure connection”.

So what I’m trying is issuing a *.domain.com and domain.com certificate and for all the custom domains the on_demain certificate.

  • :white_check_mark: custom domain on demand are working fine
  • :white_check_mark: domain.com certificate is working fine
  • :x: sub-domains certificates are not working as expected
  • :x: without the on_demand_tls ask = It’s issuing a custom certificate for each sub-domain instead of using/issuing the wildcard one - *.domain.com
  • :x: with the on_demand_tls ask = It’s not issuing the wildcard certificate for *.domain.com

4. Error messages and/or full log output:

INFO	using adjacent Caddyfile
INFO	admin	admin endpoint started	{"address": "tcp/localhost:2019", "enforce_origin": false, "origins": ["localhost:2019", "[::1]:2019", "127.0.0.1:2019"]}
INFO	http	server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS	{"server_name": "srv0", "https_port": 443}
INFO	http	enabling automatic HTTP->HTTPS redirects	{"server_name": "srv0"}
INFO	http	enabling automatic TLS certificate management	{"domains": ["*.domain.com", "domain.com"]}
INFO	autosaved config	{"file": "/root/.config/caddy/autosave.json"}
INFO	serving initial configuration
INFO	tls.obtain	acquiring lock	{"identifier": "*.domain.com"}
INFO	tls.obtain	lock acquired	{"identifier": "*.domain.com"}
INFO	tls.issuance.acme	waiting on internal rate limiter	{"identifiers": ["*.domain.com"]}
INFO	tls.issuance.acme	done waiting on internal rate limiter	{"identifiers": ["*.domain.com"]}
INFO	tls.cache.maintenance	started background certificate maintenance	{"cache": "0xc0002210a0"}
INFO	tls	cleaned up storage units
Successfully started Caddy (pid=12718) - Caddy is running in the background

ERROR	tls.obtain	will retry	{"error": "[*.domain.com] Obtain: [*.domain.com] solving challenges: *.domain.com: no solvers available for remaining challenges (configured=[tls-alpn-01 http-01] offered=[dns-01] remaining=[dns-01]) (order=https://acme.zerossl.com/v2/DV90/order/XXXX) (ca=https://acme.zerossl.com/v2/DV90)", "attempt": 1, "retrying_in": 60, "elapsed": 3.098332016, "max_duration": 2592000}

I’m using Google Domains for the DNS and have those settings:

@    A       SERVER_IP
*    CNAME   domain.com
www  CNAME   domain.com # not sure if needed since I'm using the * now

5. What I already tried:

Without the :443 block the tls.obtain returns a error (added at 4) for the *.domain.com but it works for the domain.com certificate.

Added the ask directive so the subdomains (200 if it exists and 404 otherwise) arent getting issued as userX.domain but the *.domain.com certificates isnt issued too.

6. Links to relevant resources:


Thanks for the awesome project and support!

I’ve tried creating two automation policies like this post but without success, also tried using a Caddyfile like this other post and had the same “no solvers” error.

ERROR	tls.obtain	will retry	{"error": "[*.domain.com] Obtain: [*.domain.com] solving challenges: *.domain.com: no solvers available for remaining challenges (configured=[http-01 tls-alpn-01] offered=[dns-01] remaining=[dns-01]) (order=https://acme.zerossl.com/v2/DV90/order/xxxx) (ca=https://acme.zerossl.com/v2/DV90)", "attempt": 1, "retrying_in": 60, "elapsed": 2.993847201, "max_duration": 2592000}
ERROR	tls.obtain	will retry	{"error": "[*.domain.com] Obtain: [*.domain.com] solving challenges: *.domain.com: no solvers available for remaining challenges (configured=[http-01 tls-alpn-01] offered=[dns-01] remaining=[dns-01]) (order=https://acme.zerossl.com/v2/DV90/order/yyyy) (ca=https://acme.zerossl.com/v2/DV90)", "attempt": 2, "retrying_in": 120, "elapsed": 65.445825567, "max_duration": 2592000}
ERROR	tls.obtain	will retry	{"error": "[*.domain.com] Obtain: [*.domain.com] solving challenges: *.domain.com: no solvers available for remaining challenges (configured=[http-01 tls-alpn-01] offered=[dns-01] remaining=[dns-01]) (order=https://acme.zerossl.com/v2/DV90/order/zzzz) (ca=https://acme.zerossl.com/v2/DV90)", "attempt": 3, "retrying_in": 120, "elapsed": 187.71117716, "max_duration": 2592000}
ERROR	tls.obtain	will retry	{"error": "[*.domain.com] Obtain: [*.domain.com] solving challenges: *.domain.com: no solvers available for remaining challenges (configured=[http-01 tls-alpn-01] offered=[dns-01] remaining=[dns-01]) (order=https://acme.zerossl.com/v2/DV90/order/wwww) (ca=https://acme.zerossl.com/v2/DV90)", "attempt": 4, "retrying_in": 300, "elapsed": 310.45877065, "max_duration": 2592000}

I’m not sure if this is a caddy wildcard problem or some other configuration (DNS?) because it works for domain.com and sub.domain.com (when on_demand is active - issuing a certificate with CN sub.domain.com).

Also checked with a basic Caddyfile and got the same error.

*.domain.com

reverse_proxy localhost:3000

forcing the zerossl issuer I’ve got the same error:

domain.com:443, *.domain.com:443 {
   
  reverse_proxy localhost:3000
	tls {
		issuer zerossl
	}	

}
INFO	tls.issuance.acme.acme_client	trying to solve challenge	{"identifier": "domain.com", "challenge_type": "http-01", "ca": "https://acme.zerossl.com/v2/DV90"}
ERROR	tls.obtain	will retry	{"error": "[*.domain.com] Obtain: [*.domain.com] solving challenges: *.domain.com: no solvers available for remaining challenges (configured=[http-01 tls-alpn-01] offered=[dns-01] remaining=[dns-01]) (order=https://acme.zerossl.com/v2/DV90/order/xxxxx) (ca=https://acme.zerossl.com/v2/DV90)", "attempt": 1, "retrying_in": 60, "elapsed": 1.912255346, "max_duration": 2592000}
INFO	tls.issuance.acme	served key authentication	{"identifier": "domain.com", "challenge": "http-01", "remote": "91.199.212.xxx:53520"}
INFO	tls.issuance.acme.acme_client	validations succeeded; finalizing order	{"order": "https://acme.zerossl.com/v2/DV90/order/yyyyy"}
INFO	tls.issuance.acme.acme_client	successfully downloaded available certificate chains	{"count": 1, "first_url": "https://acme.zerossl.com/v2/DV90/cert/zzzz"}
INFO	tls.obtain	certificate obtained successfully	{"identifier": "domain.com"}
INFO	tls.obtain	releasing lock	{"identifier": "domain.com"}
WARN	tls	stapling OCSP	{"error": "no OCSP stapling for [domain.com]: parsing OCSP response: ocsp: error from server: unauthorized"}

To get wildcard certificates, you must configure the DNS challenge. It’s a requirement by the ACME CAs to properly validate that you control the entire DNS zone.

1 Like

Thanks @francislavoie! For some reason I thought caddy had some “magic” for the wildcards certificats too (which is almost impossible since they need some kind of restrict access to the DNS records).

I’ve moved my DNS to route53 since I’m using AWS for everything and it worked!


For the record, my steps:

  1. Download the custom caddy build

You can get the url at the Download Caddy page

curl 'https://caddyserver.com/api/download?os=linux&arch=amd64&p=github.com%2Fcaddy-dns%2Froute53&idempotency=20494704131839' -o caddy

  1. Move the binary (ex to: /usr/bin/caddy) and update its permissions (ex: 755 +x);
  2. Check if its working caddy version;
  3. Check if it has the route53 dns module caddy list-modules | grep route53;
  4. Go to AWS console and create the user/group/policy with this permissions: GitHub - libdns/route53: AWS Route53 provider implementation for libdns (change the hostedzone/ZABCD1EFGHIL with your zone ID);
  5. Create the ~/.aws/credentials file with the generated credentials;
[default]
aws_access_key_id = your_access_key_id
aws_secret_access_key = your_secret_access_key
  1. Update your Caddyfile (or json) to use the route53 module:
*.domain.com {
  # ....
  tls {
   dns route53
 }
}
  1. Start/reload caddy
1 Like

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