ARI - acmesh-official/acme.sh GitHub Wiki
acme.sh implements ACME Renewal Information (RFC 9773) automatically. No flag, no opt-in, no configuration needed. And if you do pass --days or --valid-to, your own schedule wins â unless the CA wants the cert renewed sooner.
If your CA exposes a renewalInfo endpoint in its ACME directory (Let's Encrypt, ZeroSSL, Sectigo, SSL.com, âĻ), acme.sh will use it. If the CA does not, acme.sh falls back to the classic 30-day fixed-interval rule â behavior is identical to before.
| What | When | Why |
|---|---|---|
đ Polls suggestedWindow
|
Every cron run, before deciding to skip | Lets the CA shift renewal forward in case of an incident (key compromise, mass revocation) |
| đ¯ Picks a random renewal time inside the window | Right after a successful issuance/renewal | Disperses renewals across the network so all clients don't hit the CA at the same instant. Skipped when you pinned a schedule and the window is later than it |
| đ Updates the renewal time | Every cron run, if renewal time is outside the CA's suggestedWindow
|
Adapt to CA requirements. A pinned schedule is only moved earlier, never later |
đ Sends replaces=<certID> in newOrder |
On --renew
|
Lets the CA correlate the new order with the certificate it supersedes (RFC 9773 §5) |
âŠī¸ Retries without replaces
|
If the CA returns alreadyReplaced or an ARI validation error |
Robust against edge cases (switching CAs, retired issuers, parallel renewal) |
đĸ Display explanationURL in log and notify
|
If the CA gives an explanation about the renew | Stay informed about renewals |
acme.sh renews when any one of these is true:
-
--forceis given - The cached
Le_NextRenewTimehas passed (the classic 30-day fallback, also used when no ARI)
This means a CA can effectively command an early renewal across the entire acme.sh user base by shrinking the suggested window â useful for emergency incident response.
If you never passed --days or --valid-to, the CA's window decides. That is the default, and the recommended setup.
If you did pass one of them, acme.sh treats that schedule as pinned:
| Situation | What happens |
|---|---|
| Nothing pinned | The ARI window decides |
| Nothing pinned, CA has no ARI | Classic 30-day interval (DEFAULT_RENEW) |
| Pinned, ARI wants to renew later | ARI is ignored, your schedule stands |
| Pinned, ARI wants to renew earlier | ARI wins, so an emergency renewal still gets through |
Pinned with a fixed-date --valid-to
|
ARI is skipped entirely: such a cert is not renewed automatically at all |
--days and --valid-to are only saved to the domain conf when you actually pass them â the built-in 30-day default is never written there. That is how acme.sh tells "the user asked for this" apart from "nobody said anything".
To turn ARI off completely, set NO_ARI=1 in ~/.acme.sh/account.conf, in the environment, or in the CA's ca.conf:
NO_ARI=1Renewal then follows Le_NextRenewTime alone. A renewal time ARI already wrote is not rewound by this: force one renewal to recompute it.
acme.sh --renew -d example.com --forceShort-lived certificates (Apple's 47-day proposal, Let's Encrypt's shortlived profile, etc.) are coming. With shorter lifetimes, fixed-interval renewal becomes brittle:
- A 7-day cert with a 30-day fixed renewal interval would always be expired
- All clients renewing at the same offset would hammer the CA
- Emergency revocations need a way to push the renewal time forward
ARI solves all three. The CA gets full control of when to renew; clients just follow its hints.
The chosen next-renewal time is saved in the domain conf as Le_NextRenewTimeStr:
acme.sh --info -d example.com
# Look for: Le_NextRenewTimeStr=...To see the live ARI window the CA is currently advertising, run with --debug 2:
acme.sh --renew -d example.com --debug 2 2>&1 | grep -i 'ARI suggestedWindow'Example output:
[INFO] ARI suggestedWindow: 2026-05-06T19:48:34Z to 2026-05-08T14:59:23Z
[INFO] Next renewal time picked from ARI window: 2026-05-07T16:57:49Z
-
certID for ARI requests is computed per RFC 9773 §4.1 as
base64url(AKI) + "." + base64url(Serial)of the existing certificate. -
Window pick is
start + (current_epoch % window_size). This is intentionally pseudo-random across clients (different cert issuance moments â different offsets) without needing crypto-grade randomness, and it is the same simple "use current time as entropy" pattern acme.sh already uses for cron randomization. -
Failure handling: any failure mode (ARI 404, network error, malformed response, CA does not support ARI) cleanly falls back to the original fixed-interval
Le_NextRenewTimelogic. ARI is a strict enhancement.
- Compatible with all validation modes: webroot, standalone, alpn, DNS API, DNS manual, DNS persist. ARI only changes when renewals happen, not how they validate.
-
Compatible with
--daysand--valid-to/--valid-from(Validity): an explicit schedule is pinned â ARI can pull it forward but never push it back, and a fixed-date--valid-toopts out of ARI entirely. See the section above. -
Compatible with
--cert-profile(Profile selection): independent.
- â Let's Encrypt
- â
ZeroSSL (when ACME server returns
renewalInfo) - Check your CA's directory â if it has a
"renewalInfo"field, ARI is on.
curl -s https://acme-v02.api.letsencrypt.org/directory | grep renewalInfoFull normative reference: RFC 9773 â Automated Certificate Management Environment (ACME) Renewal Information (ARI) Extension
Key sections:
- §4.1 â certID computation
- §4.2 â
suggestedWindowshape andexplanationURL - §4.3 â polling and
Retry-After - §5 â newOrder
replacesfield - §7.4 â
alreadyReplacederror code