feat: Modify the certificate auto-renewal logic. (#12430)

Refs https://github.com/1Panel-dev/1Panel/issues/12389
This commit is contained in:
CityFun
2026-04-07 09:54:38 +00:00
committed by GitHub
parent d74692a68b
commit 9e501ce02b
4 changed files with 64 additions and 36 deletions
-1
View File
@@ -51,7 +51,6 @@ type WebsiteSSLApply struct {
ID uint `json:"ID" validate:"required"`
SkipDNSCheck bool `json:"skipDNSCheck"`
Nameservers []string `json:"nameservers"`
DisableLog bool `json:"disableLog"`
}
type WebsiteSSLObtain struct {
+62 -30
View File
@@ -5,8 +5,7 @@ import (
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"github.com/go-acme/lego/v4/certificate"
"io"
"log"
"os"
"path"
@@ -14,6 +13,10 @@ import (
"strings"
"time"
"github.com/go-acme/lego/v4/certificate"
legoLogger "github.com/go-acme/lego/v4/log"
"github.com/jinzhu/gorm"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/app/model"
@@ -27,8 +30,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
"github.com/1Panel-dev/1Panel/agent/utils/ssl"
legoLogger "github.com/go-acme/lego/v4/log"
"github.com/jinzhu/gorm"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
)
type WebsiteSSLService struct {
@@ -45,6 +47,7 @@ type IWebsiteSSLService interface {
Update(update request.WebsiteSSLUpdate) error
Upload(req request.WebsiteSSLUpload) error
ObtainSSL(apply request.WebsiteSSLApply) error
AutoRenewSSL(id uint) error
SyncForRestart() error
DownloadFile(id uint) (*os.File, error)
ImportMasterSSL(create model.WebsiteSSL) error
@@ -210,13 +213,35 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
return create, nil
}
func printSSLLog(logger *log.Logger, msgKey string, params map[string]interface{}, disableLog bool) {
if disableLog {
func printSSLLog(logger *log.Logger, msgKey string, params map[string]interface{}) {
if logger == nil {
return
}
logger.Println(i18n.GetMsgWithMap(msgKey, params))
}
func newWebsiteSSLLogger(websiteSSL *model.WebsiteSSL, autoRenew bool) (*os.File, *log.Logger) {
flags := os.O_CREATE | os.O_WRONLY | os.O_TRUNC
if autoRenew {
flags = os.O_CREATE | os.O_WRONLY | os.O_APPEND
}
logFile, err := os.OpenFile(websiteSSL.GetLogPath(), flags, constant.FilePerm)
if err != nil {
global.LOG.Errorf("open ssl log file failed, domain: %s, err: %v", websiteSSL.PrimaryDomain, err)
return nil, log.New(io.Discard, "", log.LstdFlags)
}
if autoRenew {
if info, statErr := logFile.Stat(); statErr == nil && info.Size() > 0 {
_, _ = logFile.WriteString("\n")
}
_, _ = logFile.WriteString(fmt.Sprintf("========== [%s] auto renew attempt ==========\n", time.Now().Format(constant.DateTimeLayout)))
}
return logFile, log.New(logFile, "", log.LstdFlags)
}
func reloadSystemSSL(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
if !global.IsMaster {
return
@@ -226,7 +251,7 @@ func reloadSystemSSL(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
fileOp := files.NewFileOp()
certPath := path.Join(global.Dir.DataDir, "secret/server.crt")
keyPath := path.Join(global.Dir.DataDir, "secret/server.key")
printSSLLog(logger, "StartUpdateSystemSSL", nil, logger == nil)
printSSLLog(logger, "StartUpdateSystemSSL", nil)
if err := fileOp.WriteFile(certPath, strings.NewReader(websiteSSL.Pem), 0600); err != nil {
logger.Printf("Failed to update the SSL certificate File for 1Panel System domain [%s] , err:%s", websiteSSL.PrimaryDomain, err.Error())
return
@@ -239,11 +264,19 @@ func reloadSystemSSL(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
logger.Printf("Failed to update the SSL certificate for 1Panel System domain [%s] , err:%s", websiteSSL.PrimaryDomain, err.Error())
return
}
printSSLLog(logger, "UpdateSystemSSLSuccess", nil, logger == nil)
printSSLLog(logger, "UpdateSystemSSLSuccess", nil)
}
}
func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
return w.obtainSSL(apply.ID, false)
}
func (w WebsiteSSLService) AutoRenewSSL(id uint) error {
return w.obtainSSL(id, true)
}
func (w WebsiteSSLService) obtainSSL(id uint, autoRenew bool) error {
var (
err error
websiteSSL *model.WebsiteSSL
@@ -254,7 +287,7 @@ func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
resource certificate.Resource
)
websiteSSL, err = websiteSSLRepo.GetFirst(repo.WithByID(apply.ID))
websiteSSL, err = websiteSSLRepo.GetFirst(repo.WithByID(id))
if err != nil {
return err
}
@@ -306,17 +339,16 @@ func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
}
go func() {
logFile, _ := os.OpenFile(path.Join(global.Dir.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", websiteSSL.PrimaryDomain, websiteSSL.ID)), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
defer logFile.Close()
logger := log.New(logFile, "", log.LstdFlags)
legoLogger.Logger = logger
if !apply.DisableLog {
startMsg := i18n.GetMsgWithMap("ApplySSLStart", map[string]interface{}{"domain": strings.Join(domains, ","), "type": i18n.GetMsgByKey(websiteSSL.Provider)})
if websiteSSL.Provider == constant.DNSAccount {
startMsg = startMsg + i18n.GetMsgWithMap("DNSAccountName", map[string]interface{}{"name": dnsAccount.Name, "type": dnsAccount.Type})
}
logger.Println(startMsg)
logFile, logger := newWebsiteSSLLogger(websiteSSL, autoRenew)
if logFile != nil {
defer logFile.Close()
}
legoLogger.Logger = logger
startMsg := i18n.GetMsgWithMap("ApplySSLStart", map[string]interface{}{"domain": strings.Join(domains, ","), "type": i18n.GetMsgByKey(websiteSSL.Provider)})
if websiteSSL.Provider == constant.DNSAccount {
startMsg = startMsg + i18n.GetMsgWithMap("DNSAccountName", map[string]interface{}{"name": dnsAccount.Name, "type": dnsAccount.Type})
}
logger.Println(startMsg)
if websiteSSL.Provider != constant.DnsManual {
privateKey, err := ssl.GetPrivateKeyByType(websiteSSL.KeyType, websiteSSL.PrivateKey)
if err != nil {
@@ -361,7 +393,7 @@ func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
websiteSSL.Organization = cert.Issuer.Organization[0]
}
websiteSSL.Status = constant.SSLReady
printSSLLog(logger, "ApplySSLSuccess", map[string]interface{}{"domain": strings.Join(domains, ",")}, apply.DisableLog)
printSSLLog(logger, "ApplySSLSuccess", map[string]interface{}{"domain": strings.Join(domains, ",")})
saveCertificateFile(websiteSSL, logger)
if websiteSSL.ExecShell {
@@ -369,12 +401,12 @@ func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
if websiteSSL.PushDir {
workDir = websiteSSL.Dir
}
printSSLLog(logger, "ExecShellStart", nil, apply.DisableLog)
printSSLLog(logger, "ExecShellStart", nil)
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(30*time.Minute), cmd.WithLogger(logger), cmd.WithWorkDir(workDir))
if err = cmdMgr.RunBashC(websiteSSL.Shell); err != nil {
printSSLLog(logger, "ErrExecShell", map[string]interface{}{"err": err.Error()}, apply.DisableLog)
printSSLLog(logger, "ErrExecShell", map[string]interface{}{"err": err.Error()})
} else {
printSSLLog(logger, "ExecShellSuccess", nil, apply.DisableLog)
printSSLLog(logger, "ExecShellSuccess", nil)
}
}
@@ -386,9 +418,9 @@ func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(websiteSSL.ID))
if len(websites) > 0 {
for _, website := range websites {
printSSLLog(logger, "ApplyWebSiteSSLLog", map[string]interface{}{"name": website.PrimaryDomain}, apply.DisableLog)
printSSLLog(logger, "ApplyWebSiteSSLLog", map[string]interface{}{"name": website.PrimaryDomain})
if err := createPemFile(website, *websiteSSL); err != nil {
printSSLLog(logger, "ErrUpdateWebsiteSSL", map[string]interface{}{"name": website.PrimaryDomain, "err": err.Error()}, apply.DisableLog)
printSSLLog(logger, "ErrUpdateWebsiteSSL", map[string]interface{}{"name": website.PrimaryDomain, "err": err.Error()})
}
}
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
@@ -396,19 +428,19 @@ func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
return
}
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
printSSLLog(logger, "ErrSSLApply", nil, apply.DisableLog)
printSSLLog(logger, "ErrSSLApply", nil)
return
}
printSSLLog(logger, "ApplyWebSiteSSLSuccess", nil, apply.DisableLog)
printSSLLog(logger, "ApplyWebSiteSSLSuccess", nil)
}
reloadSystemSSL(websiteSSL, logger)
if websiteSSL.PushNode {
printSSLLog(logger, "StartPushSSLToNode", nil, apply.DisableLog)
printSSLLog(logger, "StartPushSSLToNode", nil)
if err = xpack.PushSSLToNode(websiteSSL); err != nil {
printSSLLog(logger, "PushSSLToNodeFailed", map[string]interface{}{"err": err.Error()}, apply.DisableLog)
printSSLLog(logger, "PushSSLToNodeFailed", map[string]interface{}{"err": err.Error()})
return
}
printSSLLog(logger, "PushSSLToNodeSuccess", nil, apply.DisableLog)
printSSLLog(logger, "PushSSLToNodeSuccess", nil)
}
}()
+1 -1
View File
@@ -41,7 +41,7 @@ func Run() {
if _, err := global.Cron.AddJob("@daily", job.NewWebsiteJob()); err != nil {
global.LOG.Errorf("can not add website corn job: %s", err.Error())
}
if _, err := global.Cron.AddJob("@daily", job.NewSSLJob()); err != nil {
if _, err := global.Cron.AddJob("0 */6 * * *", job.NewSSLJob()); err != nil {
global.LOG.Errorf("can not add ssl corn job: %s", err.Error())
}
minuteRand, err := rand.Int(rand.Reader, big.NewInt(60))
+1 -4
View File
@@ -46,10 +46,7 @@ func (ssl *ssl) Run() {
continue
}
} else {
if err := sslService.ObtainSSL(request.WebsiteSSLApply{
ID: s.ID,
DisableLog: true,
}); err != nil {
if err := sslService.AutoRenewSSL(s.ID); err != nil {
global.LOG.Errorf("Failed to update the SSL certificate for the [%s] domain , err:%s", s.PrimaryDomain, err.Error())
continue
}