impl App { pub async fn reload_certificates(self: &Arc) -> Result { self.reload_certificate_snapshot(None).await } pub async fn reload_certificate( self: &Arc, certificate_id: &str, ) -> Result { if !crate::config::valid_id(certificate_id) { return Err(ApiError( StatusCode::NOT_FOUND, "certificate not found".into(), )); } self.reload_certificate_snapshot(Some(certificate_id)).await } async fn reload_certificate_snapshot( self: &Arc, certificate_id: Option<&str>, ) -> Result { let _lock = self.update_lock.lock().await; let previous = self.config.load_full(); let desired = previous.envelope.config.clone(); if let Some(certificate_id) = certificate_id { let certificate = desired .tls .certificates .iter() .find(|certificate| certificate.id == certificate_id) .ok_or_else(|| ApiError(StatusCode::NOT_FOUND, "certificate not found".into()))?; if certificate.issuer.is_some() { return Err(ApiError( StatusCode::CONFLICT, "managed certificates are reloaded by the renewal pipeline".into(), )); } } let desired_vhost_count = desired.vhosts.len(); let observed = self.docker.snapshot().await; let policy = self.policy.clone(); let defaults = self.startup_listeners; let active_listeners = self.active_listeners.clone(); let revision = previous.envelope.revision; let prepared = tokio::task::spawn_blocking(move || { let effective = crate::docker::effective_config(desired, &observed)?; let mut prepared = config::compile_with_active( effective, revision, &policy, defaults, Some(&previous), &active_listeners, )?; prepared .envelope .config .vhosts .truncate(desired_vhost_count); Ok::<_, anyhow::Error>(prepared) }) .await .map_err(|_| { ApiError( StatusCode::INTERNAL_SERVER_ERROR, "certificate reload task failed".into(), ) })? .map_err(|error| ApiError(StatusCode::UNPROCESSABLE_ENTITY, format!("{error:#}")))?; self.config.store(Arc::new(prepared)); crate::acl::dynamic::config_changed(); if let Some(certificate_id) = certificate_id { tracing::info!( revision, certificate_id, "configured certificate reloaded from disk" ); } else { tracing::info!(revision, "configured certificates reloaded from disk"); } Ok(revision) } }