diff --git a/cmd/web_acme.go b/cmd/web_acme.go index 512a990e02..68fd5d00d8 100644 --- a/cmd/web_acme.go +++ b/cmd/web_acme.go @@ -6,6 +6,7 @@ package cmd import ( "crypto/x509" "encoding/pem" + "errors" "fmt" "net" "net/http" @@ -93,10 +94,21 @@ func runACME(listenAddr string, m http.Handler) error { myACME := certmagic.NewACMEIssuer(magic, certmagic.DefaultACME) magic.Issuers = []certmagic.Issuer{myACME} - // this obtains certificates or renews them if necessary - err := magic.ManageSync(graceful.GetManager().HammerContext(), []string{setting.Domain}) + // Obtain certificates or renew them if necessary. ManageSync fails closed on + // renewal errors even when a still-valid certificate is already on disk, which + // takes HTTPS down on restart (https://github.com/go-gitea/gitea/issues/38519). + // Prefer keeping the existing cert and retrying renewals asynchronously. + ctx := graceful.GetManager().ShutdownContext() + err := magic.ManageSync(ctx, []string{setting.Domain}) if err != nil { - return err + cert, cacheErr := magic.CacheManagedCertificate(ctx, setting.Domain) + if cacheErr != nil || cert.Expired() { + return errors.Join(err, cacheErr) + } + log.Error("ACME certificate manage failed; continuing with existing certificate: %v", err) + if err := magic.ManageAsync(ctx, []string{setting.Domain}); err != nil { + log.Error("Failed to start async ACME management: %v", err) + } } tlsConfig := magic.TLSConfig()