public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH proxmox-backup] acme: partially fix #6372: scale certificate renewal checks by lifetime
@ 2026-04-21 14:46 Manuel Federanko
  0 siblings, 0 replies; only message in thread
From: Manuel Federanko @ 2026-04-21 14:46 UTC (permalink / raw)
  To: pbs-devel

Start renewing a certificate once 2/3 of its total lifetime have passed,
instead of the hardcoded 30 days. This stays consistent with many
certificates, which are valid for 90 days.

The update service runs daily, impose a 3 day minimum remaining lifetime
to still be able to handle transient failures for certificate renewals.

Signed-off-by: Manuel Federanko <m.federanko@proxmox.com>
Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=6372
---
 src/api2/node/certificates.rs          | 21 +++++++++++++++++++--
 src/bin/proxmox-daily-update.rs        |  3 ++-
 src/bin/proxmox_backup_manager/acme.rs |  3 ++-
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/src/api2/node/certificates.rs b/src/api2/node/certificates.rs
index a69f6511..6e7b3326 100644
--- a/src/api2/node/certificates.rs
+++ b/src/api2/node/certificates.rs
@@ -306,16 +306,33 @@ pub fn new_acme_cert(force: bool, rpcenv: &mut dyn RpcEnvironment) -> Result<Str
 /// parameter is set).
 pub fn renew_acme_cert(force: bool, rpcenv: &mut dyn RpcEnvironment) -> Result<String, Error> {
     if !cert_expires_soon()? && !force {
-        bail!("Certificate does not expire within the next 30 days and 'force' is not set.")
+        let lead = cert_renew_lead_time()? / (24 * 60 * 60);
+        bail!("Certificate does not expire within the next {lead} days and 'force' is not set.")
     }
 
     spawn_certificate_worker("acme-renew-cert", force, rpcenv)
 }
 
+/// When to start checking for new certs.
+pub fn cert_renew_lead_time() -> Result<i64, Error> {
+    let cert = pem_to_cert_info(get_certificate_pem()?.as_bytes())?;
+    if let (Some(notafter), Some(notbefore)) =
+        (cert.not_after_unix().ok(), cert.not_before_unix().ok())
+    {
+        // gets usually checked every day by the daily-update service,
+        // start checking at least 3 days before expiry
+        let lifetime = notafter - notbefore;
+        let lead = std::cmp::max(lifetime / 3, 3 * 24 * 60 * 60);
+        Ok(lead)
+    } else {
+        Ok(30 * 24 * 60 * 60)
+    }
+}
+
 /// Check whether the current certificate expires within the next 30 days.
 pub fn cert_expires_soon() -> Result<bool, Error> {
     let cert = pem_to_cert_info(get_certificate_pem()?.as_bytes())?;
-    cert.is_expired_after_epoch(proxmox_time::epoch_i64() + 30 * 24 * 60 * 60)
+    cert.is_expired_after_epoch(proxmox_time::epoch_i64() + cert_renew_lead_time()?)
         .map_err(|err| format_err!("Failed to check certificate expiration date: {}", err))
 }
 
diff --git a/src/bin/proxmox-daily-update.rs b/src/bin/proxmox-daily-update.rs
index c4d68e30..e5e96eb9 100644
--- a/src/bin/proxmox-daily-update.rs
+++ b/src/bin/proxmox-daily-update.rs
@@ -75,7 +75,8 @@ async fn check_acme_certificates(rpcenv: &mut dyn RpcEnvironment) -> Result<(),
     }
 
     if !api2::node::certificates::cert_expires_soon()? {
-        log::info!("Certificate does not expire within the next 30 days, not renewing.");
+        let lead = api2::node::certificates::cert_renew_lead_time()? / (24 * 60 * 60);
+        log::info!("Certificate does not expire within the next {lead} days, not renewing.");
         return Ok(());
     }
 
diff --git a/src/bin/proxmox_backup_manager/acme.rs b/src/bin/proxmox_backup_manager/acme.rs
index 57431225..d1a2323f 100644
--- a/src/bin/proxmox_backup_manager/acme.rs
+++ b/src/bin/proxmox_backup_manager/acme.rs
@@ -415,7 +415,8 @@ pub fn plugin_cli() -> CommandLineInterface {
 async fn order_acme_cert(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
     if !param["force"].as_bool().unwrap_or(false) && !api2::node::certificates::cert_expires_soon()?
     {
-        println!("Certificate does not expire within the next 30 days, not renewing.");
+        let lead = api2::node::certificates::cert_renew_lead_time()? / (24 * 60 * 60);
+        println!("Certificate does not expire within the next {lead} days, not renewing.");
         return Ok(());
     }
 
-- 
2.47.3




^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-04-21 14:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-21 14:46 [PATCH proxmox-backup] acme: partially fix #6372: scale certificate renewal checks by lifetime Manuel Federanko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal