Any public certificate authority could technically issue a certificate for your domain if someone passes its validation, for example through a DNS hijack or a misconfigured server. A CAA record (Certification Authority Authorization) lists which CAs are allowed to issue certificates for your domain. Every public CA must check CAA before issuing, and refuse if it isn’t on the list.
What a CAA record looks like
example.com. CAA 0 issue "letsencrypt.org"
| Part | Meaning |
|---|---|
0 |
Flags (0 normally; 128 = “critical”) |
issue |
Tag: which CA may issue regular certificates |
"letsencrypt.org" |
The CA’s identifying domain |
Other tags:
issuewild— which CA may issue wildcard certificates (*.example.com). If absent,issueapplies to wildcards too.iodef— where CAs can report a refused request:0 iodef "mailto:[email protected]".
Common setups
Only Let’s Encrypt:
example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 iodef "mailto:[email protected]"
Let’s Encrypt plus a commercial CA:
example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 issue "sectigo.com"
Let’s Encrypt for normal certificates, no wildcards at all:
example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 issuewild ";"
";" means nobody may issue that type.
Domain that should never get certificates:
example.com. CAA 0 issue ";"
CA identifiers for some common CAs: letsencrypt.org, sectigo.com, digicert.com, globalsign.com, pki.goog (Google Trust Services), ssl.com. CDNs often use several CAs. Cloudflare, for example, may issue via Let’s Encrypt, Google Trust Services and others for its edge certificates, and adds the records it needs automatically when it manages your DNS. Check your CDN’s documentation before restricting.
How CAA lookup works
CAs check the exact name first, then walk up the tree:
- For
shop.example.com, the CA looks for CAA atshop.example.com. If there’s none, atexample.com. - The first name that has CAA records wins.
- No CAA records anywhere means any CA may issue (the default).
So a CAA record at the root applies to all subdomains, unless a subdomain has its own CAA records.
Adding CAA records
Most DNS panels (Cloudflare, Route 53, many registrars) have a CAA type with fields for flags, tag and value. In a zone file:
example.com. 3600 IN CAA 0 issue "letsencrypt.org"
Before adding restrictions, inventory every certificate in use across your domain and subdomains: web servers, mail servers, CDNs, load balancers and SaaS products on custom domains (helpdesk, status page, shop). A forgotten service using another CA fails at its next renewal.
Verify
dig +short example.com CAA
dig +short shop.example.com CAA
Then test issuance with a staging or dry-run renewal:
sudo certbot renew --dry-run
If CAA blocks issuance, Let’s Encrypt reports an error like CAA record for example.com prevents issuance. See Let’s Encrypt with Certbot.
Advanced: account binding
Let’s Encrypt supports CAA extensions such as accounturi, which pins issuance to a specific ACME account, and validationmethods, which allows only certain challenge types:
example.com. CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/123456789"
This gives strong protection, but you must update the record if you change ACME accounts or servers.
Common mistakes
- Adding CAA for Let’s Encrypt only, while a CDN or SaaS uses another CA, so renewals there break weeks later.
- Typos in CA identifiers (
letsencrypt.cominstead ofletsencrypt.org). - Forgetting
issuewildsemantics: withissuewild ";", wildcard renewals fail. - A CNAME at the checked name. CAA lookups follow CNAMEs, so the CAA records at the target apply. That can surprise you with SaaS subdomains.
Quick reference
| Goal | Record |
|---|---|
| Only Let’s Encrypt | 0 issue "letsencrypt.org" |
| Block wildcards | 0 issuewild ";" |
| Report violations | 0 iodef "mailto:[email protected]" |
| Check | dig +short example.com CAA |
Related: SSL/TLS explained and TXT records.