Introduction

DNS CAA (Certificate Authority Authorization) records specify which Certificate Authorities are allowed to issue SSL certificates for a domain. When a CA receives a certificate request, it must check the domain's CAA records. If no CAA record authorizes that CA, the CA is required by RFC 6844 to refuse issuance. This commonly blocks Let's Encrypt certificate renewal when CAA records are configured to allow only a specific CA like DigiCert.

Symptoms

  • Let's Encrypt certbot fails with CAA record for example.com prevents issuance
  • Failed to issue certificate with reference to CAA policy
  • ACME challenge completes but certificate is not issued
  • dig example.com CAA shows records that do not include letsencrypt.org
  • Other CAs work but Let's Encrypt specifically is blocked

Common Causes

  • CAA record configured for a specific CA (e.g., digicert.com) excluding others
  • CAA record with issuewild tag not covering the specific subdomain
  • issue ";" record blocking all CAs
  • CAA record added for security compliance but not updated when switching CAs
  • Subdomain inherits restrictive CAA from parent domain

Step-by-Step Fix

  1. 1.Check current CAA records:
  2. 2.```bash
  3. 3.dig example.com CAA +noall +answer
  4. 4.# Example output:
  5. 5.# example.com. 3600 IN CAA 0 issue "digicert.com"
  6. 6.# example.com. 3600 IN CAA 0 issuewild "digicert.com"
  7. 7.`
  8. 8.Understand the CAA record format:
  9. 9.`
  10. 10.example.com. CAA 0 issue "letsencrypt.org"
  11. 11.# Flags: 0 (non-critical)
  12. 12.# Tag: issue (allows certificate issuance)
  13. 13.# Value: the authorized CA domain
  14. 14.`
  15. 15.Add Let's Encrypt to the authorized CAs:
  16. 16.```bash
  17. 17.# Add to your DNS zone file or DNS management console:
  18. 18.example.com. CAA 0 issue "letsencrypt.org"
  19. 19.example.com. CAA 0 issue "digicert.com"
  20. 20.example.com. CAA 0 issuewild ";"
  21. 21.# Multiple issue records are allowed - each authorizes a different CA
  22. 22.`
  23. 23.For Let's Encrypt specifically, also check the _acme-challenge subdomain:
  24. 24.```bash
  25. 25.dig _acme-challenge.example.com CAA +noall +answer
  26. 26.# Subdomains can have their own CAA records that override the parent
  27. 27.`
  28. 28.Verify the CAA record is visible to Let's Encrypt:
  29. 29.```bash
  30. 30.# Check from multiple resolvers (CAA is checked by the CA, not the client)
  31. 31.dig example.com CAA @8.8.8.8 +short
  32. 32.dig example.com CAA @1.1.1.1 +short
  33. 33.`
  34. 34.Retry certificate issuance after CAA update:
  35. 35.```bash
  36. 36.sudo certbot renew --force-renewal
  37. 37.# Wait for DNS propagation (CAA TTL is typically 300-3600 seconds)
  38. 38.`

Prevention

  • Always include all CAs you might use in your CAA records
  • Use CAA 0 issue "letsencrypt.org" alongside other CAs for flexibility
  • Document CAA records in your DNS change management process
  • Test certificate issuance after any CAA record changes
  • Consider using CAA iodef tag to receive email alerts about unauthorized certificate requests:
  • example.com. CAA 0 iodef "mailto:security@example.com"