fix: handle SAN certs from lego, check both backup and lego cache

This commit is contained in:
Claus Lohmar 2026-07-07 15:23:40 +01:00
parent 1eb470fa12
commit 881b94099c

View file

@ -113,12 +113,11 @@ func runCert(args []string) {
log.Fatalf("Failed to create backup dir: %v", err)
}
// Check if all domains have valid LE certs in backup
// Check if all domains have valid LE certs in backup or lego cache
needIssue := false
for _, domain := range domains {
certFile := filepath.Join(*backupDir, domain, "fullchain.pem")
keyFile := filepath.Join(*backupDir, domain, "privkey.pem")
if !fileExists(certFile) || !fileExists(keyFile) {
certFile := findCertFile(domain, *backupDir, *legoDir)
if certFile == "" {
needIssue = true
break
}
@ -186,20 +185,22 @@ func obtainCertsLego(domains []string, email, backupDir, legoDir, legoPath strin
}
// Copy certificates from lego output to backup
// Lego issues a SAN cert (single cert for all domains) named after the first domain
certDir := filepath.Join(legoDir, "certificates")
firstDomain := domains[0]
crtSrc := filepath.Join(certDir, firstDomain+".crt")
keySrc := filepath.Join(certDir, firstDomain+".key")
if !fileExists(crtSrc) || !fileExists(keySrc) {
return fmt.Errorf("lego did not produce expected cert files in %s", certDir)
}
for _, domain := range domains {
crtSrc := filepath.Join(certDir, domain+".crt")
keySrc := filepath.Join(certDir, domain+".key")
domainDir := filepath.Join(backupDir, domain)
os.MkdirAll(domainDir, 0755)
if fileExists(crtSrc) && fileExists(keySrc) {
copyFile(crtSrc, filepath.Join(domainDir, "fullchain.pem"))
copyFile(keySrc, filepath.Join(domainDir, "privkey.pem"))
log.Printf("[OK] Certificate obtained for %s", domain)
} else {
log.Printf("[WARN] Certificate files not found for %s in %s", domain, certDir)
}
copyFile(crtSrc, filepath.Join(domainDir, "fullchain.pem"))
copyFile(keySrc, filepath.Join(domainDir, "privkey.pem"))
log.Printf("[OK] Certificate obtained for %s", domain)
}
return nil
}
@ -245,6 +246,28 @@ func runDB(args []string) {
// --- Helpers ---
func findCertFile(domain, backupDir, legoDir string) string {
// Check backup first
candidates := []string{
filepath.Join(backupDir, domain, "fullchain.pem"),
filepath.Join(legoDir, "certificates", domain+".crt"),
}
// Lego issues SAN cert named after first domain — check in lego cache
entries, _ := os.ReadDir(filepath.Join(legoDir, "certificates"))
for _, e := range entries {
if strings.HasSuffix(e.Name(), ".crt") && !strings.Contains(e.Name(), ".issuer.") {
candidates = append(candidates, filepath.Join(legoDir, "certificates", e.Name()))
break
}
}
for _, c := range candidates {
if fileExists(c) && isCertFromLE(c) {
return c
}
}
return ""
}
func fileExists(path string) bool {
_, err := os.Stat(path)
return err == nil