Let's Encrypt made HTTPS free and automatic, and that turned TLS from a yearly purchase into a background process. This article explains how it works: what a certificate proves, the six steps every ACME client runs, how to choose a challenge type, the limits you can hit, and why certificate lifetimes are dropping from 90 days to 45.

It is Part 1 of two. Part 2 (opens in a new tab) shows the same ideas running on my k3s cluster, where cert-manager issues and renews a wildcard certificate with no manual step.

Why Let's Encrypt exists

Before Let's Encrypt launched in 2015, a certificate meant paying a certificate authority (CA), generating a CSR by hand, emailing proof of ownership and setting a calendar reminder to do it again in a year. Many outages blamed on "SSL" were a missed reminder.

A TLS certificate proves one thing: the server holding the private key controls the domain name in the certificate. Let's Encrypt issues Domain Validation (DV) certificates only. It does not check who you are as a company, and browsers encrypt a DV connection exactly like any other.

Three ideas make it work:

  • A protocol instead of a person. The ACME protocol (RFC 8555) lets software prove domain control and collect a certificate with no human in the loop.
  • Short lifetimes. Certificates last 90 days today and are moving to 45. A stolen key is useful for less time, and nobody can renew that often by hand, which forces automation.
  • A trusted root. Certificates chain to ISRG roots that ship in every major browser and operating system.

A note on naming: everyone says "SSL certificate", but SSL itself was retired years ago. What you get is an X.509 certificate used with TLS 1.2 or 1.3.

How ACME issuance works

Every ACME client, whether Certbot on a VM or cert-manager in a cluster, runs the same steps.

ACME issuance in eight numbered steps between a client and Let's Encrypt: register an account, create an order, receive challenges, publish the proof, validation, finalize with a CSR, signing, and installing the certificate with its chain.

  1. Register an account. The client generates an account key pair and registers the public key. Every later request is signed with this key.
  2. Create an order. The client asks for a certificate covering one or more names, for example example.com and www.example.com.
  3. Receive challenges. For each name, Let's Encrypt returns an authorization with a random token and a choice of challenge types.
  4. Answer the challenge. The client publishes a value derived from the token and its account key, at an HTTP path or in a DNS TXT record.
  5. Get validated. Let's Encrypt fetches that value from several network vantage points. If they agree, the authorization becomes valid.
  6. Finalize and download. The client sends a CSR signed by the certificate's private key. Let's Encrypt signs the certificate, logs it to Certificate Transparency and returns it with its intermediate chain.

Two keys are involved and they are easy to mix up. The account key identifies you to Let's Encrypt. The certificate key is the one your web server uses, and it never leaves your machine: only the CSR does.

Renewal is not a special operation. It is the same steps, run again before the old certificate expires.

Choosing a challenge type

Use HTTP-01 when the server is reachable on port 80. Use DNS-01 when it is not, or when you need a wildcard.

Two columns. HTTP-01: Let's Encrypt fetches a token file from port 80 of your server. DNS-01: the ACME client creates a TXT record through the DNS provider's API and Let's Encrypt looks it up.

HTTP-01DNS-01TLS-ALPN-01
Proof is placed at/.well-known/acme-challenge/TOKEN on port 80TXT record _acme-challenge.example.comA special TLS handshake on port 443
NeedsPublic port 80API access to your DNS providerPublic port 443 and a client that terminates TLS
WildcardsNoYesNo
Private or internal hostsNoYesNo
Main riskFirewalls, redirects, a CDN in frontA powerful DNS token; propagation delaysLimited client support
Typical userSingle server, Kubernetes ingressWildcards, hosts behind NAT, several clustersReverse proxies such as Caddy and Traefik

Three details catch people out with HTTP-01:

  • Validation always starts on port 80. Redirects to HTTPS are followed, but the first request is never on 443.
  • If the name has an AAAA record, validation prefers IPv6. A stale AAAA record fails the challenge even when IPv4 works.
  • Behind a load balancer, every backend must be able to serve the token, or the challenge path must be routed to the one that can.

For DNS-01, scope the API token to the single zone and to DNS edits only. A token that can rewrite all your DNS is a bigger risk than an expired certificate.

Certificate lifetimes are shrinking

The default Let's Encrypt certificate drops from 90 days to 64 days in February 2027 and to 45 days in February 2028. A CA/Browser Forum rule caps all public TLS certificates at 47 days from 15 March 2029, so every CA is moving the same way.

DateACME profileCertificate lifetimeAuthorization reuse
Until February 2027classic (default)90 days30 days
13 May 2026 (live)tlsserver (opt-in)45 days30 days
10 February 2027classic (default)64 days10 days
16 February 2028classic (default)45 days7 hours

Staging gets each change about a month earlier. There is also a shortlived profile whose certificates last about six days.

Two consequences matter more than the headline number.

Fixed renewal intervals break. A cron job that renews every 60 days is fine for a 90-day certificate and fatal for a 45-day one. Renew at about two thirds of the actual lifetime instead, or let the CA tell you when.

Every renewal becomes a real validation. Authorization reuse is the window in which Let's Encrypt skips re-checking a domain it validated recently. At 7 hours, effectively every renewal runs a fresh challenge. A challenge path that only worked on day one will fail on every renewal.

ARI: the CA tells the client when to renew

ACME Renewal Information (ARI, RFC 9773) is an endpoint the client polls for a suggested renewal window. Normally the window sits around two thirds of the lifetime. If Let's Encrypt has to revoke certificates in bulk, it moves the window earlier and clients renew before the revocation lands. Renewals made through ARI are also exempt from rate limits.

Let's Encrypt is also standardizing DNS-PERSIST-01, a challenge where the TXT record is set once and reused at every renewal. That removes the need to keep a DNS API token on the server.

Rate limits and the staging environment

Test against staging first. Production limits are easy to hit while debugging, and nobody can reset them for you.

LimitValueWhat usually triggers it
New certificates per registered domain50 per 7 daysMany subdomains issued in one week
Same exact set of hostnames5 per 7 daysDeleting and re-creating one certificate in a loop
New orders per account300 per 3 hoursA misbehaving client retrying
Failed validations per hostname5 per hourA broken challenge path being retried

The second row is the one people hit. A Secret or a certificate file gets deleted, the client requests again, something is still misconfigured, and after five rounds that set of names is locked out for days.

Staging has the same API at a different URL, with much higher limits:

Production: https://acme-v02.api.letsencrypt.org/directory
Staging:    https://acme-staging-v02.api.letsencrypt.org/directory

Staging certificates are signed by an untrusted root, so browsers show a warning. That is expected. Once issuance and renewal work on staging, switch the URL and issue once on production.

Common mistakes

Most Let's Encrypt outages come from renewal, not first issuance.

MistakeWhat happensFix
Renewal never testedFirst issuance works, renewal fails 60 days laterForce a renewal on staging before going live
Port 80 closed after setupHTTP-01 renewals failKeep port 80 open and redirect to HTTPS instead of blocking
Serving only the leaf certificateBrowsers work, curl and some mobile clients failServe the full chain
Hardcoded 60-day renewalBreaks when lifetimes drop to 45 daysRenew at two thirds of the lifetime, or use ARI
No expiry monitoringYou find out from usersAlert when any certificate has under 14 days left
Debugging on productionRate-limited for a weekUse staging until it works end to end
Web server not reloadedNew certificate on disk, old one in memoryUse a deploy hook, or a proxy that reloads certificates itself

One change makes monitoring non-optional: Let's Encrypt stopped sending expiry reminder emails in June 2025. If renewal breaks, nothing outside your own alerting will tell you.

Where to go next

Let's Encrypt is a protocol you automate once, not a certificate you buy. Pick the challenge type that fits your network, prove it on staging, renew by lifetime fraction instead of a fixed day count, and alert on expiry.

In Part 2 (opens in a new tab) I apply this to a k3s cluster: cert-manager, a Cloudflare DNS-01 issuer, one wildcard certificate on an Istio gateway, and renewals that need nobody.