TLS Cert LCM

Automated Renewal & Expiry Alerting

How Versus keeps managed TLS certificates from expiring — an ARI-aware renewal sweep that launches the cert-renew workflow at the right moment, a days-before-expiry fallback, an expiring-soon API, and per-certificate notification contacts.

A certificate that expires unnoticed is an outage. Versus treats renewal as a managed lifecycle, not a calendar reminder: for every certificate it issues, it tracks the expiry, decides when renewal should happen, and then drives the full reissue-and-redeploy through the same workflow engine that issued it in the first place. Renewals reach the same ADC virtual servers and SSL profiles the original certificate was deployed to — no operator has to remember which box served which name.

This page covers the renewal side of certificate lifecycle: how Versus decides a certificate is due, how it renews it, and how you surface what's expiring. Issuance, deployment, and discovery are covered in Certificates.


What Versus tracks per certificate

Every certificate Versus manages is a ManagedCertificate record. The fields that drive renewal and alerting are:

FieldPurpose
not_before / not_afterValidity window, parsed from the issued leaf certificate.
days_until_expiryDerived from not_after — days remaining, or negative once expired.
auto_renewWhether the renewal sweep is allowed to renew this certificate automatically (default on).
statusLifecycle state — including issued, deployed, expiring, expired, revoked.
ari_cert_idThe ACME ARI certificate identifier, computed at issuance.
ari_renewal_afterThe earliest renewal time the CA suggested via ARI, cached on the record.
deployment_mode / deployment_targetsThe deployment intent carried forward, so a renewal redeploys exactly where the original went.
notification_contactsWho to notify on expiry / renewal — a list of {type, value, label} entries.

Because deployment intent is stored on the certificate, renewal is a closed loop: Versus reissues the same names from the same CA and pushes the result back to the same targets, in the same mode (overwrite in place, or rename_update — a new dated object plus an SSL-profile rebind).


When is a certificate "due"? ARI first, calendar second

Versus does not blindly renew at a fixed number of days. It prefers the CA's own advice.

ACME Renewal Information (ARI)

For certificates issued from an ACME CA, Versus queries ACME Renewal Information (ARI, draft-ietf-acme-ari). ARI lets the CA publish a suggested renewal window for a specific certificate — which matters because CAs increasingly shorten lifetimes and occasionally need to trigger early mass-renewals (for example, to retire a misissued batch). Versus:

  1. Computes the ARI certID from the leaf certificate (a base64url hash of the issuer name plus the encoded serial).
  2. Fetches the CA's renewalInfo resource for that certID.
  3. Reads back the suggestedWindow (start / end) and caches start on the record as ari_renewal_after.
  4. Renews once now is at or past the window start.

If the CA doesn't advertise a renewalInfo endpoint, or returns 404 for the certificate, ARI is simply skipped and Versus falls back to the calendar.

Days-before-expiry fallback

When there's no usable ARI answer, Versus renews when the certificate enters a fixed window before expiry — by default 30 days. The threshold is not_after − N days; once now crosses it, the certificate is due. This fallback also covers internally-signed certificates (the built-in Versus CA and AD CS drivers), which have no ARI to consult.


The renewal sweep

Renewal is driven by a management command, check_cert_renewals, that you run on a recurring schedule (a cron entry, a systemd timer, or your platform's scheduled-task mechanism — typically daily).

# Renew everything that's due
python manage.py check_cert_renewals

# Report what would happen, launch nothing
python manage.py check_cert_renewals --dry-run

# Override the fallback threshold (e.g. renew 45 days out)
python manage.py check_cert_renewals --days 45

Each run:

  1. Selects every ManagedCertificate with auto_renew=True whose status is issued, deployed, expiring, or expired.
  2. For ACME-backed certificates, fetches ARI and caches the suggested window on the record.
  3. Applies the ARI decision, or the --days fallback, to decide renew now vs skip.
  4. For each certificate that's due, launches the cert-renew workflow, scoped to the certificate's tenant.

The command prints a per-certificate line and a summary, so it's safe to read in cron mail or a scheduler log:

Checking 24 auto-renew certificate(s)…
  SKIP  wildcard.corp.example: Not yet in renewal window (threshold 2026-09-01)
  RENEW api.example.com: ARI window opened at 2026-08-18 02:00:00+00:00
  RENEW legacy.example.net: Within 30d renewal window (expires 2026-09-10)

Done: 2 renewal(s) queued, 22 skipped, 0 error(s).

Use --dry-run first when you're tuning thresholds or validating a new fleet — it evaluates and reports every certificate but launches no workflows.


What the cert-renew workflow does

The sweep doesn't renew certificates itself — it starts a durable workflow run and hands off. This is deliberate: renewals then get the same visibility, retries, back-out, and audit trail as any other change, and an operator can watch or intervene in the console. See Running Workflows via the API for how to drive and supervise these runs programmatically.

The built-in cert-renew workflow runs, in order:

StepWhat happens
Renew Certificate (cert.trigger_renew)Loads the certificate and its stored deployment targets into the run context.
Check Renewal Timing (ARI) (cert.check_ari)A decision step. Re-checks ARI, falls back to the fallback_days_before_expiry config (default 30), and branches yes / no.
Generate New Key & CSRA fresh key and CSR — renewals get new key material, not a re-sign of the old key.
ACME DNS-01 OrderReissues from the same CA via a DNS-01 challenge, solved through your Versus-managed DNS device.
Store Renewed CertificateParses the new leaf, updates serial, fingerprint, not_before / not_after, and re-derives ari_cert_id.
Deploy to ADCsPushes the new certificate and key to every stored deployment target, honoring the certificate's deployment_mode.
Verify TLSOpens a TLS connection to each target and confirms a certificate is being served.

The ARI decision step has a graceful "Not Yet Due" exit: if a run is started but the certificate turns out not to be in its renewal window, the workflow ends cleanly instead of forcing an early reissue. That makes the workflow safe to trigger manually — from the certificate's Renew action or the API — without second-guessing the timing.

Because cert-renew is a normal workflow definition, you can open it in the Workflow Builder, clone it, insert an approval gate, or add extra verification steps for a specific environment.


Surfacing what's expiring

Expiring-soon API

The managed-certificate API exposes a purpose-built endpoint for dashboards and monitoring integrations:

GET /api/certs/certificates/expiring_soon/?days=30
Authorization: Bearer …

It returns managed certificates whose not_after falls within the next days (default 30) and whose status is issued, deployed, or expiring, ordered by soonest expiry. Each entry carries common_name, not_after, days_until_expiry, auto_renew, and ari_renewal_after — enough to build an at-a-glance "renewing soon / at risk" view, or to alert on anything that's close to expiry but not set to auto-renew.

You can also filter the full list by lifecycle state, for example everything Versus considers already expiring or expired:

GET /api/certs/certificates/?status=expiring
GET /api/certs/certificates/?auto_renew=false

Notification contacts

Each certificate carries a notification_contacts list — the people or groups tied to that certificate for expiry and renewal correspondence. Every entry is typed, so a contact can be an email address, an AD group, or a ServiceNow group:

[
  { "type": "email",            "value": "[email protected]",   "label": "TLS Team" },
  { "type": "ad_group",         "value": "PKI-Operators",          "label": "PKI Operators" },
  { "type": "servicenow_group", "value": "Network Security",       "label": "NetSec Queue" }
]

You set these when you request the certificate (the New Certificate Request step accepts them), and they travel with the record for the life of the certificate — so ownership is recorded alongside the certificate rather than in a separate spreadsheet.

Approval-time email

When a certificate from a public ACME CA requires approval (governed by the system-wide cert_approval_required_public_ca setting), the issuance and renewal workflows send an email to your Admin and Cert Approver users asking them to review the request, with the CN, SANs, requesting user, and run number. Internally-signed certificates (Versus CA, AD CS) skip the gate. Approvals themselves are actioned from the console or the API — see the approve / reject actions on the certificate.


Discovered (unmanaged) certificates

Renewal automation applies to certificates Versus manages. For certificates it merely finds — the existing SSL objects already on your F5 BIG-IP, NetScaler, A10, Kemp, or Avi devices — the Discover & Import Certificates workflow scans each ADC and records every certificate, its subject/issuer, expiry date, and computed days-until-expiry, into the inventory view. Run discovery on a schedule to keep that expiry data fresh, and use it to find third-party certificates that predate Versus and should be brought under management. Once a discovered certificate is adopted as a ManagedCertificate, it joins the renewal loop above.

See F5 BIG-IP Integration for how Versus reads and writes SSL profiles on the ADC side.


Operating checklist

  • Schedule the sweep. Run check_cert_renewals daily. Start with --dry-run on a new fleet, then remove it.
  • Leave ARI on. For public ACME certificates, ARI gives the CA a way to pull renewals forward when it must — you want that signal honored automatically.
  • Set the fallback to your comfort window. --days (and the workflow's fallback_days_before_expiry) governs internally-signed and non-ARI certificates. Thirty days is the default; widen it for slow change-approval processes.
  • Watch the expiring-soon endpoint. Alert specifically on certificates that are close to expiry and have auto_renew=false — those are the ones nothing will renew for you.
  • Record contacts at request time. Populate notification_contacts so certificate ownership is captured on the record.
  • Keep deployment targets accurate. Renewal redeploys to the stored targets; if a certificate moved to new virtual servers, update its targets so the renewal lands in the right place.

How it fits the platform

Renewal sits on top of the same building blocks as the rest of Versus: certificates and their history live in the relational system of record, secrets and private keys are protected by the Versus Vault, and every reissue runs as a durable, auditable workflow that reaches your devices through the outbound-only collector plane described in Platform Architecture. The renewal sweep is just the scheduler that decides when to pull that lever — the lever itself is ordinary, inspectable automation.


Related