Skip to main content

https

CAA Records and Let's Encrypt

Configure CAA without accidentally blocking certificate renewal: trace inheritance, understand issuewild precedence, and test the exact CA and hostname set used by your platform.

Published
Updated
Reviewed

Source review: Checked against RFC 8659 and current Let's Encrypt documentation for CAA lookup, issue and issuewild precedence, issuer identifiers, and validation parameters.

CAA records let a domain owner state which certificate authorities may issue certificates containing a DNS name. They are an issuance authorization control, not a replacement for ACME validation, certificate monitoring, or correct TLS configuration.

With no applicable CAA restriction, any public CA may issue after completing its normal validation. With a restrictive CAA RRset, every name in the certificate request has to be authorized. A precise policy reduces the set of allowed issuers; an inaccurate policy can stop a hosting platform from issuing or renewing HTTPS.

Find the relevant CAA RRset before editing anything

CAA is not simply “read the apex record.” RFC 8659 defines a tree walk:

  1. Query CAA at the requested name.
  2. If no CAA RRset is found, remove the left-most label and query the parent.
  3. Stop at the first non-empty CAA RRset.
  4. Do not merge that RRset with records higher in the tree.

For www.api.example.com, the search is conceptually:

www.api.example.com  -> no CAA
api.example.com      -> no CAA
example.com          -> CAA found; stop here

This is often described as inheritance, but nearest policy wins is more precise. A CAA RRset at api.example.com replaces the parent policy for that branch; it does not add to it. A child override can therefore tighten or accidentally loosen the effective issuer list.

For a wildcard request such as *.preview.example.com, the relevant lookup begins at preview.example.com and then climbs toward example.com. The literal asterisk is not a separate place where operators normally publish the policy.

CAA lookup also follows DNS aliases. If docs.example.com is a CNAME to a hosting-provider name, CAA at the target can become relevant. Check both the source configuration and the canonical target instead of assuming the apex policy is the only one involved.

issue controls wildcard issuance unless issuewild exists

This is the rule that causes the most configuration mistakes.

  • issue authorizes a CA for ordinary names.
  • If the relevant RRset has no issuewild property, issue also controls wildcard issuance.
  • If the relevant RRset has at least one issuewild property, all issue properties are ignored for wildcard requests and the issuewild set takes precedence.
  • issuewild is ignored for non-wildcard requests.

One issuer for normal and wildcard certificates

This single record allows Let’s Encrypt for both ordinary names and wildcards because no issuewild record exists:

example.com.  300  IN  CAA  0 issue "letsencrypt.org"

You do not need to add issuewild merely because a wildcard certificate exists.

Different issuers for normal and wildcard certificates

example.com.  300  IN  CAA  0 issue     "platform-ca.example"
example.com.  300  IN  CAA  0 issuewild "letsencrypt.org"

Here, platform-ca.example is authorized for ordinary names. For wildcard requests, the presence of issuewild makes the CA ignore the issue record and consider only letsencrypt.org.

Allow wildcard issuance but forbid ordinary issuance

example.com.  300  IN  CAA  0 issue     ";"
example.com.  300  IN  CAA  0 issuewild "letsencrypt.org"

The empty issuer in issue ";" requests that no CA issue for ordinary names, while the explicit issuewild authorization permits Let’s Encrypt wildcard issuance.

If an RRset contains issuewild but no issue, the wildcard policy is restricted while ordinary issuance is not restricted by an issue property. Add an explicit issue rule when ordinary-name behavior must also be controlled.

Multiple records of the same tag are additive. Two non-empty issue records authorize both listed CAs. Combining issue ";" with a non-empty issue record does not cancel the non-empty authorization.

Confirm the real issuer used by the platform

Do not infer the CA from the certificate currently in the browser. Hosting platforms may use different issuers for initial issuance, renewal, fallback, or different product tiers.

Before publishing CAA:

  • read the hosting provider’s current custom-domain documentation
  • identify every CA the provider says it may use
  • check whether apex, subdomain, and wildcard certificates use the same issuer
  • include every DNS name in a multi-SAN certificate in the policy review
  • name an owner who will update CAA during a provider migration

Let’s Encrypt’s CAA issuer identifier is:

letsencrypt.org

The identifier is not an ACME server URL and should not include https://.

If the rollout also needs wildcard issuance, remember that Let’s Encrypt requires DNS-01 for wildcard certificates. The wildcard DNS and TLS guide separates that validation requirement from CAA authorization.

Inspect exact names, parents, and aliases

Start with direct queries:

dig example.com CAA +short
dig api.example.com CAA +short
dig www.api.example.com CAA +short
dig docs.example.com CNAME +short

An empty child answer does not mean there is no effective CAA policy; the CA may find one at the parent. Record the first non-empty RRset for each certificate name.

Use an authoritative nameserver when caches make a change ambiguous:

dig example.com NS +short
dig @ns1.dns-provider.example example.com CAA +short
dig @ns1.dns-provider.example api.example.com CAA +short

Then compare a public recursive resolver after the change:

dig @1.1.1.1 example.com CAA +short
dig @8.8.8.8 example.com CAA +short

CAA has a TTL like other DNS data. A correct authoritative change may not affect a CA lookup until an older cached RRset expires.

Illustrative CAA verification

The image below shows the shape of a CAA query beside an HTTPS check. It is not certificate issuance evidence from a live domain.

Illustrative terminal-style CAA lookup and HTTPS verification for example domains

Illustrative example using reserved example domains and IPs.

Use advanced parameters only with an owner

Let’s Encrypt documents optional parameters that can narrow its authorization further:

example.com.  300  IN  CAA  0 issue "letsencrypt.org; validationmethods=dns-01"

validationmethods can restrict the allowed ACME challenge method. accounturi can restrict issuance to a specific ACME account. These controls can reduce risk, but they also create dependencies on automation and account ownership. Do not add them without documenting the ACME client, account, recovery path, and migration procedure.

The flags field is normally 0. A value of 128 sets the issuer-critical flag: a CA that does not understand the property tag must not issue. That behavior is useful for a deliberately critical extension, but setting it casually can turn an unknown tag or typo into an outage.

Diagnose issuance failure in the right order

When issuance fails after a CAA change:

  1. List every DNS name in the certificate request.
  2. Find the nearest non-empty CAA RRset for each name.
  3. Follow CNAMEs and inspect relevant target policy.
  4. Apply issuewild precedence only to wildcard identifiers.
  5. Confirm the platform’s actual issuer identifier.
  6. Query authoritative and public resolvers to account for TTLs.
  7. Check for SERVFAIL, timeout, or DNSSEC validation errors.
  8. Retry against a staging CA environment before consuming production issuance attempts.

A CAA SERVFAIL is not the same as an empty answer. A CA cannot safely assume issuance is allowed when DNS errors prevent it from determining whether a restrictive RRset exists.

Also remember what CAA does not do:

  • it does not revoke an existing certificate
  • it does not guarantee that an authorized CA will issue
  • it does not prove the web server is using the new certificate
  • it does not make an expired or name-mismatched certificate valid

After issuance, verify the actual public certificate:

openssl s_client \
  -connect docs.example.com:443 \
  -servername docs.example.com \
  </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

Change CAA with a rollback path

Use a controlled sequence:

  1. Record the current CAA RRsets, TTLs, certificate issuer, expiry, and ACME account owner.
  2. Confirm the future policy supports every active hosting platform and certificate name.
  3. Publish the new RRset and verify it at authoritative nameservers.
  4. Wait for the previous TTL where the timing matters.
  5. Run a staging renewal or issuance test using the production hostname pattern.
  6. Verify the resulting certificate and application response.
  7. Keep the prior known-good RRset ready for rollback.
  8. Recheck CAA whenever a domain, wildcard, CDN, or hosting provider is added to the public hostname inventory.

CAA is most effective when the policy is small and explicit. If ordinary and wildcard certificates use the same CA, one issue record is usually clearer than duplicating it with issuewild. Add the second tag only when the wildcard authorization is intentionally different.

Sources and further reading

Vendor behavior can change. Use these primary sources to confirm the current product-specific details.

Continue learning

  1. 01
    Subdomain Setup: DNS, Routing, and HTTPS

    Plan a subdomain as a complete public endpoint: choose the record, prepare host routing, account for DNS caches, and verify TLS and application behavior.

    Read
  2. 02
    Local Development with Custom Domains

    Use custom domains locally without turning your setup into a guessing game. This guide covers hosts files, local DNS, HTTPS, and when to use a real public subdomain.

    Read
  3. 03
    Vercel Custom Domain DNS Setup

    Point a Vercel project at a custom domain without confusing DNS ownership, project routing, HTTPS issuance, and redirect behavior.

    Read