Skip to main content

Renewal & rotation

How CertAutoPilot decides when to renew, what it does on success, what it does on failure, and how the 47-day SC-081 readiness score is computed.

Imported certificates are exempt

Imported (bring-your-own) certificates have no issuing CA, so none of the renewal automation on this page applies to them: auto_renew is forced off, the scheduler sweep skips them, and Manual Renew is rejected. They still flip to expired at their notAfter and still emit expiring-soon notifications — the "renewal" for an imported cert is a manual Re-import. They count as non-automatable in the 47-day readiness score.

The renewal window

By default, a certificate is renewed when 30 days remain until expiry. Override per-certificate via the renewal threshold.

If the threshold is greater than or equal to the certificate's whole lifetime, it cannot apply — the renewal date is then clamped to the midpoint of the certificate's lifetime instead. A 47-day certificate left on the 30-day default therefore renews at about 23 days, not 30. Set an explicit threshold for short-lived certificates rather than relying on the default.

Renewal mode: threshold or ARI

A certificate renews on one of two schedules.

  • custom (default) — the threshold above.
  • ari — the CA's own ACME Renewal Info window. The scheduler refreshes it at least every 6 hours (or sooner if the CA asks, clamped to 1–24 h) and overwrites the next renewal date with the CA's suggestion, so the threshold no longer governs. ARI applies only to active, auto-renew ACME certificates — never to AD CS. If an ARI query fails, the last known window is kept rather than falling back to the threshold. The scheduler sweep runs hourly by default (configurable 5–1440 minutes via renewal_check_interval_minutes in Settings → General); certs that crossed the threshold since the last run are enqueued for renewal.

Recommended thresholds per certificate validity (set them yourself — the platform applies the flat 30-day default unless you change it):

ValidityRecommended renewal at
≤ 30 days (47-day mode)14 days remaining
90 days30 days remaining
1 year30 days remaining
≥ 2 years60 days remaining

Key rotation

Renewal can either reuse the existing private key or generate a new one on a cadence. Default is reuse — the same key is kept across renewals unless you opt a certificate into rotation (key_rotation_policy: rotate with rotate_key_every_n controlling the cadence). Each key serves exactly rotate_key_every_n renewal certificates — 1 generates a new key on every renewal.

Reuse the key only when the consumer has the public key pinned somewhere (HPKP-like patterns; some IoT devices). Pinning is rare today.

Renewal failure

If the renewal fails, the scheduler retries with escalating backoff: 15 min, then 1 h, 6 h and 12 h. With the default of 5 attempts the ladder exhausts in roughly 19 hours, after which the certificate is marked renewal_failed and a notification fires. (A fifth 24-hour step exists in the table but is never reached at the default attempt count — the attempt counter trips the terminal check first.)

A safety net keeps retrying until expiry

renewal_failed is no longer a dead end: a scheduler safety net picks the certificate back up roughly every 2 days (24 h cool-down after the last failure, then a fresh backoff ladder) for as long as it has not actually expired. Failure notifications are de-duplicated to at most one per certificate per day, and certificates stuck on the ladder keep receiving expiring-soon warnings. An operator can still intervene at any time with Retry now, or stop the retries entirely by disabling auto-renew.

Post-renewal hooks

After a successful renewal, two things happen:

  1. Distribution. Every target attached to this cert is invoked — fan-out, dry-run optional, with optional auto-rollback. Auto-rollback fires only when the run finishes failed or partial and at least one target actually changed (a run that failed to connect anywhere left every target on the old certificate, so there is nothing to roll back), and never for a fanned-out run — re-deploying the previous version while sibling batches still push the new one would race. Roll a fanned-out distribution back manually once it completes.
  2. Custom hooks. An optional Webhook target receives the default payload — certificate_id, distribution_id, cert_fingerprint, domains, cert_pem, chain_pem, fullchain_pem, and private_key_pem when the module config enables it. See the webhook module for the exact schema rather than relying on this summary. Use it to invalidate caches, refresh service-mesh sidecars, or kick a CDN purge.

Revocation

Revocation is deliberately a separate manual action — never automatic. From the certificate detail page, choose Revoke, pick a reason code (key-compromise, superseded, etc.), and submit. CertAutoPilot calls the CA's revoke endpoint, marks the certificate revoked, and emits an audit event.

Revoked certs are kept in the inventory; they're not deleted. The status filter on the certificates list defaults to active; toggle to see revoked.

47-day readiness score (SC-081)

The dashboard widget computes a weighted score out of 100 — not a single percentage, and not a conjunction of conditions:

  • 50% — share of certificates with auto-renew enabled.
  • 30% — share with at least one distribution target.
  • 20% — share not using manual DNS validation.

80 or above reads as ready, 50–79 as at risk, below 50 as critical.

This is the practical floor for surviving Apple's proposed 47-day TLS-cert validity max. Aim for 100% in production.

API

POST /api/v1/projects/{project}/certificates/{id}/renew
POST /api/v1/projects/{project}/certificates/{id}/revoke
GET /api/v1/projects/{project}/dashboard/readiness-47day

See also