// Engineering Log
HTTP, HTTPS and TLS: Part 11 — Let's Encrypt Certificates: ACME, domain validation, CAA and Certificate Transparency
Published on 2026-10-19
// Fast route
This article belongs to the topic Security and protection.
Let’s Encrypt — a free certificate authority that issues DV certificates automatically, without applications or payment. Issuance and renewal are done via the ACME protocol (Automatic Certificate Management Environment, RFC 8555): a program on the server proves it controls the domain, obtains the certificate and installs it in the web server. ZeroSSL, Google Trust Services, Buypass and other CAs work via the same protocol; how they differ from Let’s Encrypt — in the overview “Beyond Let’s Encrypt”. Certificate lifetimes are shrinking, and in the coming years manual issuance will become practically impossible, so this part is worth configuring correctly once.
How ACME works
- Account. The client creates an account at the CA — a key pair used to sign all subsequent requests. Email is optional; since June 2025 Let’s Encrypt no longer sends expiration reminders, so you’ll need to track expirations yourself.
- Order. The client lists the names for the certificate:
example.ru,www.example.ru. - Challenges. For each name the CA issues a challenge that only the domain or server owner can fulfill.
- Performing the challenge. The client places the response and the CA checks it from multiple points on the Internet.
- Issuance. The client sends a CSR with its public key and downloads the certificate with the intermediate.
A successful domain validation is considered valid for a reuse period (authorization reuse) — currently up to 30 days; by 2028 Let’s Encrypt will shorten this to 7 hours.
Three challenge types
HTTP-01. The client places a file with the token at http://example.ru/.well-known/acme-challenge/<token>, and the CA downloads it.
- requires an open port 80 — no other port can be specified; the CA follows redirects to HTTPS;
- the domain must point to this server;
- not suitable for wildcard certificates;
- if there are multiple servers behind a load balancer, the file must be accessible on all of them (or the validation request must reach the one where the client runs).
DNS-01. The client creates a TXT record _acme-challenge.example.ru with the token. Step-by-step setup for Cloudflare and Route 53 — in the article “SSL certificates via DNS”.
- the only way to obtain a wildcard
*.example.ru; - no open port or public server access required — suitable for internal services with a public domain;
- the client needs access to the DNS provider’s API. To avoid giving it the key for the whole zone, delegate the challenge:
_acme-challenge.example.ru CNAME _acme-challenge.acme-zone.example.net— and issue a key only for the service zone (this is how acme-dns works, for example); - after creating the record you must wait until it is visible from all authoritative DNS servers for the zone.
Let’s Encrypt is preparing a method DNS-PERSIST-01, where the TXT record is created once and does not change on each renewal.
TLS-ALPN-01. Validation on port 443: the CA connects with ALPN acme-tls/1, and the server responds with a special temporary certificate. Convenient when port 80 is closed. Mainly used by embedded clients — Caddy, Traefik, lego; does not work with certbot and standard Nginx.
ACME clients
certbot — the EFF client, available in packages for most distributions.
# issue with automatic Nginx configuration
certbot --nginx -d example.ru -d www.example.ru
# issue only, the challenge file is placed in the site's directory
certbot certonly --webroot -w /var/www/letsencrypt -d example.ru -d www.example.ru \
--deploy-hook 'systemctl reload nginx'
# wildcard via DNS API (plugin required, e.g. python3-certbot-dns-cloudflare)
certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.cf.ini \
-d example.ru -d '*.example.ru'
# test renewal without issuing
certbot renew --dry-runThe certbot package installs a systemd timer or cron job that calls certbot renew twice a day. Certificates are stored in /etc/letsencrypt/live/<name>/: fullchain.pem — the certificate with the intermediate (this is what you point to in Nginx), privkey.pem — the key. --deploy-hook is executed only after a successful renewal and reloads the web server; without it Nginx will continue to serve the old certificate.
acme.sh — a shell client with no dependencies, supports more than a hundred DNS providers.
acme.sh --set-default-ca --server letsencrypt # by default acme.sh uses ZeroSSL
acme.sh --issue --dns dns_cf -d example.ru -d '*.example.ru'
acme.sh --install-cert -d example.ru \
--fullchain-file /etc/nginx/ssl/example.ru.crt \
--key-file /etc/nginx/ssl/example.ru.key \
--reloadcmd 'systemctl reload nginx'Built-in ACME. Caddy and Traefik issue and renew certificates themselves for each site in the configuration. Nginx has an official dynamic module ngx_http_acme_module (package nginx-module-acme) since 2025. If the web server supports ACME itself, a separate client is not needed.
Kubernetes — cert-manager: certificates are described as resources, issuance and renewal happen inside the cluster.
Lifetimes and profiles
Let’s Encrypt certificates have traditionally been 90 days. The project is moving to shorter lifetimes via ACME profiles — the client chooses a profile when ordering:
classic— default profile: 90 days; from February 10, 2027 — 64 days, from February 16, 2028 — 45 days;tlsserver— from May 13, 2026 issues 45-day certificates, for those who want to move earlier;shortlived— about 6 days. Such certificates can also be issued for IP addresses.
This aligns with the CA/Browser Forum decisions: the maximum lifetime of any public certificate — 200 days from March 2026, 100 days from March 2027, 47 days from March 2029.
Implications:
- renew roughly at two-thirds of the lifetime, not “30 days before expiry”: for a 45-day certificate, 30 days is almost the entire lifetime;
- use a client that supports ARI (ACME Renewal Information, RFC 9773): the CA indicates when to renew, for example during a mass revocation. Renewals via ARI do not consume rate limits;
- any manual step — copying a certificate to another server, uploading to a control panel, updating in a router — must be automated or avoided.
Let’s Encrypt rate limits
The most notable:
- 50 certificates per registered domain per 7 days — for
example.ruincluding all subdomains; - 5 certificates with the same set of names per 7 days — usually hit when a script or container issues a certificate on each start instead of using a saved one;
- 5 failed validations per hour for a single name per account;
- 300 new orders per 3 hours per account.
For testing use the staging server (in certbot — the --staging or --test-cert flag): rate limits there are much higher and certificates are untrusted. Renewals with the same set of names do not count toward the 50 certificates per domain limit.
CAA records
CAA (Certification Authority Authorization, RFC 8659) — a DNS record that lists certificate authorities allowed to issue certificates for a domain. CAs are required to check it before issuing. If the record is absent, anyone can issue.
example.ru. 3600 IN CAA 0 issue "letsencrypt.org"
example.ru. 3600 IN CAA 0 issuewild ";"
example.ru. 3600 IN CAA 0 iodef "mailto:security@example.ru"issue— who can issue normal certificates;issuewild— who can issue wildcards;";"— nobody;iodef— where to report attempted policy-violating issuances (CAs do not always support this).
You can restrict not only the CA but also the account and the validation method (RFC 8657):
example.ru. CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/123456789; validationmethods=dns-01"A CAA record applies to subdomains until the subdomain has its own record. If your site is behind a CDN that issues certificates itself (Cloudflare, for example, uses Let’s Encrypt and Google Trust Services), don’t forget to add those CAs, otherwise the CDN won’t be able to renew the certificate. Check with: dig CAA example.ru.
Certificate Transparency
Certificate Transparency (CT) — a system of public logs where CAs record every issued public certificate. Since 2018 Chrome, followed by Safari and Firefox, accept a certificate only if it contains Signed Certificate Timestamps (SCTs) proving logging. It’s impossible to issue a trusted certificate secretly.
Why this matters to a domain owner:
- detect unauthorized issuance. If someone obtained a certificate for your domain — via DNS compromise, a CA mistake or a former contractor — it will appear in the log;
- understand that your names are public. Every certificate reveals all names in the SAN. If a certificate is issued for
grafana.example.ruortest-crm.example.ru, that name becomes visible to everyone within minutes, including scanners that monitor CT logs and immediately check new hosts for vulnerabilities.
Search the logs with crt.sh:
curl -s 'https://crt.sh/?q=%25.example.ru&output=json' \
| jq -r '.[].name_value' | sort -u%25 is the encoded % character; the pattern means “any subdomain”. Free CT monitoring services such as Cert Spotter provide alerts for new certificates on your domain.
How to avoid exposing internal names:
- for internal services issue a wildcard
*.example.ru— the log will contain only the wildcard pattern, not every name; - or use an internal CA (step-ca): its certificates are not written to CT logs;
- do not assume “nobody knows the address” — CT makes any name from a public certificate discoverable.
Common mistakes
cert.peminstead offullchain.pemin Nginx — incomplete chain.- Renewal works, but no
--deploy-hookor--reloadcmd— the web server serves the old certificate until restarted. - Issuing a certificate on every container start — hits the 5 duplicate certificates per week limit, and the service ends up without a certificate.
- Closing port 80 “for security” — breaks HTTP-01.
- CAA allows only Let’s Encrypt, but the CDN issues certificates with another CA — renewal on the CDN silently fails.
- Monitoring not configured assuming emails from Let’s Encrypt, which no longer arrive.
// Similar task
If you are dealing with something similar
This article belongs to one of the main working topics. You can keep reading on the topic, go to the homepage to understand what I do, or open the service pages directly.
Article topic
Security and protection
SSL, hardening, access control, service protection, and secure configurations.
Typical tasks behind this topic
- Set up SSL, certificates, and secure connections
- Restrict access and close unnecessary entry points
- Harden server and service configuration
// Next step
If you need help with this topic, not just another article, it is better to go straight to the service page. The homepage and topic collection stay available as secondary routes.
Open services// Contact
Need help?
Get in touch with me and I'll help solve the problem
I reply within one business day (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related