def domainsToCert = [ [ false, 'plecianki.pl'], [ false, 'kopama.com.pl'], [ false, 'kopana.com.pl'], [ false, 'bodypainter.eu'], [ false, 'themself.eu', "massage" ], [ false, "artiks.tk" ], [ false, "arti24.eu", "api", "angular", "plecianki"], [ false, "katb.pl"], [ false, "kursy.kopama.pl"], [ false, "statistics.kopama.pl"] ] def createCert(domains) { def baseCertPath = env.CERTS_PATH ?: '/_docker_data_/letsencrypt/live' def workDir = env.WORK_DIR ?: "/_sd_/_programs_/proxy-nginx/deploy-this/lets-encrypt" def letsEncryptCommand = "docker compose --file lets-encrypt.yml --env-file lets.env" def email = env.LETSENCRYPT_EMAIL ?: 'kusartur@gmail.com' def toCreateDomains = [] for (domain in domains) { def force = domain[0] def name = domain[1] def fileName = "${baseCertPath}/${name}/cert.pem" def currentDomains = [] def daysLeft = null if (fileExists(fileName)) { // ✅ poprawne pobieranie SAN def certInfo = sh( script: """ openssl x509 -in ${fileName} -noout -ext subjectAltName \ | sed -n 's/ *DNS://gp' \ | tr ',' '\\n' \ | sed 's/^ *//' """, returnStdout: true ).trim() if (certInfo) { currentDomains = certInfo.split('\\n').collect { it.trim() } } // ✅ poprawne liczenie dni try { def expiryUnix = sh( script: "date -d \"\$(openssl x509 -enddate -noout -in ${fileName} | cut -d= -f2)\" +%s", returnStdout: true ).trim().toLong() def nowUnix = sh(script: "date +%s", returnStdout: true).trim().toLong() daysLeft = (expiryUnix - nowUnix) / (60 * 60 * 24) } catch (e) { echo "Cannot parse expiry for ${name}" } } def subList = (domain.size() > 2) ? domain[2..-1] : [] def expectedDomains = [name] + subList.collect { "${it}.${name}" } def needsRenewal = force || !fileExists(fileName) || currentDomains.size() != expectedDomains.size() || !currentDomains.containsAll(expectedDomains) || (daysLeft != null && daysLeft < 30) if (needsRenewal) { echo "Renewing '${name}' (force=${force}, expires in=${daysLeft ?: 'unknown'} days)" toCreateDomains.add(domain) } else { echo "Certificate for '${name}' OK (expires in ${daysLeft} days)" } } if (!toCreateDomains.isEmpty()) { dir(workDir) { for (domain in toCreateDomains) { def name = domain[1] def subList = (domain.size() > 2) ? domain[2..-1] : [] def subDomains = subList.collect { "-d ${it}.${name}" }.join(' ') def cmd = """ ${letsEncryptCommand} run --rm certbot certonly \ --webroot -w /var/www/certbot \ --cert-name ${name} \ --non-interactive --agree-tos \ --preferred-challenges http \ --email ${email} \ --force-renewal \ -d ${name} ${subDomains} """.stripIndent() sh(cmd) } } } else { echo "All certificates are up to date." } } pipeline { agent any stages { stage('Make https cert for my domains') { steps { script { createCert(domainsToCert) } } } } }