ACME: How Certificate Issuance Became an API Call

Getting a TLS certificate used to mean email, paperwork, and pasting a CSR into a web form. ACME turned it into a protocol a script runs at 3am. Here's the mechanism — and what we traded for it.

The last time I bought a certificate the old way, the ceremony went like this. Generate a key and a certificate signing request on the server, taking care not to fat-finger the OpenSSL invocation. Paste the CSR into a web form. Receive an email at a magic address — admin@ the domain, or one off an approved list — click a link to prove I could read that inbox. Wait. Download a zip with the certificate and, if I was lucky, the right intermediate chain. Figure out which order the chain went in. Install it without taking the site down. Set a calendar reminder for a year later, which I would ignore, and then the certificate would expire on a Saturday.

Every step in that list was a human doing something a machine could have done. ACME is the protocol that noticed.

It’s easy to credit Let’s Encrypt with making certificates free, and it did, but “free” is the less interesting half. The interesting half is that getting a certificate stopped being a transaction between a person and a company and became a conversation between two programs. The IETF standardized that conversation as RFC 8555 in 2019, years after Let’s Encrypt shipped the first version in 2015. Today a certificate renewal is a cron job that nobody watches, and the fact that nobody watches it is the entire point.

What the machine actually proves

Strip away the tooling and a certificate is a small, dull claim: the holder of this key controls this domain name. That’s it. A Domain Validation certificate has never asserted anything grander — not that you’re a real business, not that you’re honest, just that at issuance time you could demonstrate control of the name. The old email dance was a clumsy way to check that claim, and it leaned on an assumption that was already crumbling: that a human reads mail at admin@.

ACME’s insight is that “controls the domain” should be provable by a program, because in practice the thing that controls a domain is a program — the web server answering on port 80, or the DNS zone answering queries. So the protocol asks you to prove control the way software can: change something only the controller could change, and let the CA go look.

Here’s the shape of it. Your client generates an account key pair and registers it with the CA; from then on every request is signed with that key, so the CA knows it’s talking to the same party throughout. Replay is blocked by a nonce the server hands out and demands back on the next request. You place an order for a set of domain names. For each name the CA returns an authorization with one or more challenges — pick one, satisfy it, tell the CA to check. When every authorization is valid, you send the CSR, the CA issues, and you download the chain. No inbox, no zip file, no human in the loop after the first setup.

Three ways to prove control

The challenges are where the design gets opinionated, and they’re worth knowing because choosing the wrong one is most of the pain people hit.

http-01 is the default and the one everybody meets first. The CA gives your client a token; the client serves a specific string — the token joined to a hash of your account key — at http://yourdomain/.well-known/acme-challenge/<token>, on port 80, plain HTTP. The CA fetches that URL and checks the contents. It proves you control what answers on port 80 for that name. It cannot issue wildcards, because controlling www.example.com’s web root says nothing about the whole zone. And it needs port 80 reachable from the outside, which is a genuine constraint behind some firewalls and load balancers.

dns-01 proves control of the DNS zone instead of a web path. You publish a TXT record at _acme-challenge.yourdomain whose value is a hash of the key authorization, and the CA resolves it. This is the only challenge that can issue wildcard certificates, because proving you can write the zone proves control over every name under it. The catch is real and worth saying out loud: automating dns-01 means handing your ACME client credentials to write DNS records. A lot of wildcard setups quietly grant a renewal script an API token that can rewrite the zone. That token is now part of your attack surface, sitting on the box that renews certs.

tls-alpn-01 is the specialist, standardized separately in RFC 8737. The CA connects to port 443 and negotiates a special ALPN protocol, acme-tls/1; your server answers with a self-signed certificate carrying the challenge response in an extension. Nothing touches port 80 and nothing touches your normal web content, which makes it the right tool when a TLS-terminating load balancer owns 443 and you want validation to happen there. Most people never need it, and that’s fine.

Automation was the whole bet

Once you see issuance as an API call, the shorter-certificate story stops being a separate debate and becomes the same one.

Ninety-day lifetimes felt hostile when Let’s Encrypt shipped them, and they’d be genuinely hostile if renewal were still a human chore — nobody wants to paste a CSR into a form four times a year. They only work because ACME made renewal unattended. The industry’s march toward ever-shorter certificates — down past 90 days, heading for 47 by 2029 — is only survivable because the proof-of-control step is a protocol a daemon speaks, not a task a person remembers. Some servers, Caddy being the clearest example, took this to its conclusion and just do ACME themselves with no certificate management exposed to the operator at all. The certificate became an implementation detail of turning the server on.

That’s the good version of the trade: expiry dates stop being a source of Saturday outages, and short lifetimes shrink the window a leaked key stays dangerous.

What we handed to the challenge

Automation didn’t remove risk; it moved it, and it’s worth being honest about where it went.

Under the old model, forging a certificate for a domain you didn’t own meant defeating a certificate authority — social-engineering their validation staff, or compromising their signing key. Under ACME, it means beating the domain-control check for the length of one validation. If an attacker can answer http-01 for your name — by hijacking port 80, poisoning a path on a shared host, or intercepting the CA’s validation request in transit — they can get a genuine, publicly-trusted certificate for your domain, and it will look exactly like yours because it is like yours. The threat moved from “steal the vault” to “win a thirty-second race against a fetch.” That’s not obviously worse, but it’s different, and it’s why the serious CAs now validate from multiple network vantage points at once: if the CA checks your challenge from several places around the internet and they must all agree, a localized route hijack no longer fools it. That mitigation exists precisely because automation made the validation moment the thing worth attacking.

And there’s a concentration cost. One protocol, a small number of ACME certificate authorities, and a single issuer covering a few hundred million domains means the failure modes are correlated now. When Let’s Encrypt found a bug in how it rechecked CAA records in 2020, the fix was to revoke millions of certificates on short notice — a fire drill for a large slice of the web at once, because a large slice of the web renews the same way from the same place. Automation gives you a single lever, which is wonderful right up until someone has to pull it.

The honest version

ACME didn’t just automate a chore. It redefined what the chore was proving. The old ritual dressed up domain control as an act of paperwork — a human at an organization filed a request and read an email. ACME dropped the costume and made the proof match the claim exactly: a machine that can answer a challenge for this name, right now, gets a certificate for this name, right now. That’s a smaller, more honest thing to assert, and it’s cheap enough to reassert every sixty days.

The whole edifice leans on one load-bearing assumption — that answering the challenge is hard for anyone who isn’t you. That was always the soft spot in domain validation; ACME didn’t create it. What ACME did was exercise that check a million times a day, automatically, for most of the encrypted web. When the assumption holds, you never think about certificates again, which is the point. When it doesn’t, the thing that made issuance effortless is the same thing that makes the failure wide. Both of those are true at once, and pretending otherwise is how you get surprised.

Continue the conversation

← Back to Blog