Renewal Information (ARI)
acme-proxy implements the ACME Renewal Information extension (RFC 9773). ARI
allows a CA to signal to ACME clients when they should ideally renew their
certificates. This prevents the “stampede” effect where thousands of
certificates expire simultaneously, and allows the CA to orchestrate graceful
mass-revocations by shortening the renewal window.
GET /renewalInfo/{certID}
This is an unauthenticated endpoint clients use to ask “when should I renew this certificate?”. The response provides a time window (Start and End).
The window is resolved in this order:
- Revoked certificates win. If the certificate is known to be revoked locally (looked up by its serial), the answer is a window entirely in the past, prompting a compliant client to renew immediately. This is checked before the signer backend is consulted, so a locally revoked certificate is never talked out of renewing by an upstream CA that has not noticed yet.
- The backend’s own opinion, if it has one. The
relaybackend relays the upstream CA’s answer verbatim, including RFC 9773 §4.2’s optionalexplanationURL— so if Let’s Encrypt signals early renewal, that reaches your internal clients unchanged. Thecustombackend can do the same through itsrenewal_infohook, but only whensigner.custom.supports_renewal_info = true; otherwise the hook is never invoked. - A local estimate, when the backend has no opinion — always the case for
local_ca. The certificate’snotBeforeandnotAfterare read by parsing the certificate itself, and the suggested window runs from ⅔ to ¾ of the validity period. For a 90-day certificate that is roughly day 60 to day 67, leaving a comfortable margin before expiry rather than running up to it.
Spreading clients across that window is what prevents the “stampede” effect where a whole fleet renews at the same moment.
The replaces field
During a newOrder request, an ARI-aware client can include a replaces field
containing the certID of the certificate it intends to replace.
acme-proxy validates it against all three of RFC 9773 §5’s correspondence
rules. The certID is decoded into an Authority Key Identifier and a serial
number, the predecessor order is looked up, and then:
- The AKI must match the predecessor’s issuer — the serial alone is not enough, since serials are only unique per issuer. (A certificate stored before this check existed may have no recorded AKI; that case falls back to matching on serial alone, for backwards compatibility.)
- The predecessor must belong to the requesting account. You cannot claim to replace someone else’s certificate.
- The new order must share at least one identifier with the predecessor. A renewal that covers none of the same names is not a replacement.
Failing any of them is malformed; an unknown certID likewise.
Concurrency guard: a client cannot have two orders replacing the same
predecessor. A second newOrder naming a replaces value already claimed gets
409 alreadyReplaced. An order that later becomes invalid releases its claim,
so a failed attempt does not permanently block a retry.
The accepted replaces value is stored and reflected back on the 201 response
and on every subsequent poll of the order.