SSL-certifikat levetid: fra 2029 holder certifikater kun 47 dage
Levetiden på et SSL-certifikat bliver skåret ned i tre trin: 200 dage fra marts 2026, 100 dage fra marts 2027 og 47 dage fra marts 2029. Det har browserne og certifikatudstederne besluttet i fællesskab. Her er tidsplanen, forskellen på et gratis og et betalt SSL-certifikat, hvad det koster, og hvordan I sørger for, at fornyelsen kører af sig selv, så webshoppen aldrig står med en advarsel i browseren. Til teknikeren er der kommandoer til at læse udløbsdatoen, teste fornyelsen og sætte CAA-poster og overvågning op.
Hassan Aziz
Partner & Projektleder, Bullmade
Hvad der er besluttet
Et SSL-certifikat, eller mere præcist et TLS-certifikat, er det, der giver jeres site hængelåsen og https i adresselinjen. Certifikatet gør to ting: det beviser over for browseren, at den taler med det rigtige domæne, og det sørger for, at trafikken mellem kunden og serveren er krypteret. Det gælder alt fra login og kontaktformularer til adresser og betalingsoplysninger i checkout.
Teknisk set er certifikatet et X.509-dokument med en offentlig nøgle, de domænenavne, det gælder for (feltet Subject Alternative Name, SAN), og to tidsstempler: notBefore og notAfter. Browseren afviser certifikatet, hvis klokken ligger uden for det interval, eller hvis domænet i adresselinjen ikke står i SAN-feltet. Det er notAfter, de nye regler handler om.
Hvor længe et certifikat må være gyldigt, bestemmer den enkelte udbyder ikke selv. Reglerne bliver lavet i CA/Browser Forum, hvor certifikatudstederne (CA'erne) og browserproducenterne sidder sammen. I april 2025 vedtog forummet afstemning SC-081, som gradvist sænker den maksimale levetid fra 398 dage til 47 dage.
Afstemningen sluttede den 11. april 2025. Blandt certifikatudstederne stemte 25 for, ingen imod og 5 undlod. Alle fire browserproducenter med stemmeret, Apple, Google, Microsoft og Mozilla, stemte for. Det er altså ikke et forslag længere, men en vedtaget regel, som alle offentligt betroede certifikatudstedere skal følge.
Første trin trådte i kraft den 15. marts 2026, så de certifikater, I har fået udstedt siden da, er allerede kortere end før. Næste trin kommer den 15. marts 2027.
Tidsplanen fra 2026 til 2029
Ændringen sker i tre trin, og hvert trin rammer to ting: hvor længe certifikatet må gælde, og hvor længe certifikatudstederen må genbruge den kontrol af domænet, den har lavet tidligere.
| Certifikater udstedt fra | Maksimal levetid | Genbrug af domænekontrol |
|---|---|---|
| Før 15. marts 2026 | 398 dage | 398 dage |
| 15. marts 2026 | 200 dage | 200 dage |
| 15. marts 2027 | 100 dage | 100 dage |
| 15. marts 2029 | 47 dage | 10 dage |
Domænekontrollen er det trin, hvor udstederen tjekker, at I faktisk har kontrol over domænet, typisk ved at I lægger en fil på serveren, opretter en DNS-post eller klikker på et link i en mail. I dag kan en udsteder genbruge den kontrol i mange måneder. Fra 2029 må den kun genbruges i 10 dage, så i praksis skal domænet kontrolleres igen ved næsten hver eneste fornyelse.
Det sidste tal er det, der får betydning for driften. Når kontrollen skal laves forfra ved hver fornyelse, skal den metode, I bruger til at bevise kontrol, virke hver gang og uden et menneske ind over. En DNS-post, som nogen opretter i hånden én gang om året, holder ikke.
For certifikater med virksomhedsoplysninger (OV og EV) gælder der også en grænse for, hvor længe oplysningerne om virksomheden må genbruges. Den gik fra 825 til 398 dage den 15. marts 2026.
Reglerne gælder for nye certifikater. Et certifikat, der er udstedt før en skæringsdato, gælder sin levetid ud. Men ved den næste fornyelse efter datoen får I den kortere levetid.
Let's Encrypt, som er den største udsteder af gratis certifikater, går hurtigere frem end reglerne kræver. Let's Encrypt styrer levetiden med såkaldte profiler, som ACME-klienten kan bede om:
| Profil | Levetid i dag | Genbrug af domænekontrol | Bemærkning |
|---|---|---|---|
classic | 90 dage | 30 dage | Standard, hvis klienten ikke vælger andet |
tlsserver | 45 dage | 7 timer | Til fuldt automatiserede opsætninger |
shortlived | 160 timer, cirka 6 dage | 7 timer | Ikke for alle, skal vælges aktivt |
Og standardprofilen bliver strammet i to trin:
| Dato | Hvad Let's Encrypt ændrer |
|---|---|
| 13. maj 2026 | Profilen tlsserver udsteder 45-dages certifikater. Den skal vælges aktivt |
| 10. februar 2027 | Standardprofilen classic går fra 90 til 64 dage, og domænekontrollen må genbruges i 10 dage |
| 16. februar 2028 | classic går ned til 45 dage, og domænekontrollen må kun genbruges i 7 timer |
Bruger I Let's Encrypt via jeres hosting, er det altså februar 2027 og februar 2028, I skal holde øje med, ikke 2029. Certbot kan vælge profil med --preferred-profile, som falder tilbage til standardprofilen, hvis profilen ikke findes, eller --required-profile, som lader udstedelsen fejle i stedet.
Hvorfor levetiden bliver kortere
Begrundelsen er sikkerhed. Hvis en angriber får fat i den private nøgle til et certifikat, eller hvis et certifikat bliver udstedt til den forkerte, kan det misbruges, så længe det er gyldigt. Jo kortere levetid, jo kortere tid kan et fejludstedt eller kompromitteret certifikat bruges. Det er den begrundelse, Let's Encrypt selv giver.
Et certifikat kan godt tilbagekaldes, før det udløber, men det kræver, at browseren slår op og får et svar, og det sker ikke altid. Udløbsdatoen virker derimod hver gang. Let's Encrypts profil shortlived er netop så kort, at certifikaterne slet ikke behøver information om tilbagekaldelse.
Den anden begrundelse er, at korte levetider tvinger automatisering frem. Let's Encrypt skriver selv, at automatisering er helt afgørende for både brugervenlighed og driftssikkerhed, og at 90 dage oprindeligt blev valgt, fordi det var kort nok til at skubbe folk mod automatisering, men langt nok til, at man kunne klare det i hånden. Med 47 dage er manuel fornyelse ikke længere en realistisk plan.
For en webshop er konsekvensen enkel: Den dag, hvor nogen husker at forny certifikatet en gang om året, er forbi. Fra 2029 skal et certifikat fornyes cirka hver måned, og det skal ske automatisk.
Gratis eller betalt SSL-certifikat
Søger man på SSL-certifikat pris, får man både gratis og betalte tilbud. Krypteringen er den samme. Forskellen ligger i, hvad udstederen har kontrolleret, før certifikatet blev udstedt:
| Type | Hvad der kontrolleres | Typisk pris | Egner sig til |
|---|---|---|---|
| DV (domænevalideret) | At I har kontrol over domænet | Gratis via Let's Encrypt eller Cloudflare, ellers betalt | Langt de fleste webshops og firmasites |
| OV (organisationsvalideret) | Domænet og at virksomheden findes | Betalt | Krav fra kunder, myndigheder eller interne politikker |
| EV (udvidet validering) | Domænet og en grundigere kontrol af virksomheden | Betalt, og dyrest | Særlige krav, fx i finanssektoren |
Et gratis SSL-certifikat fra Let's Encrypt er domænevalideret. Let's Encrypt tager ikke betaling for certifikaterne, men skriver selv, at nogle hostingudbydere tager et mindre gebyr for at sætte dem op. Let's Encrypt udsteder ikke OV- eller EV-certifikater og har ingen planer om det. Cloudflare udsteder også gratis certifikater til alle sites på platformen, også på gratisplanen, og fornyer dem automatisk.
Prisen på betalte certifikater varierer meget mellem udstedere og forhandlere, så vi angiver ikke et tal her. Sammenlign det, I faktisk får: valideringsniveau, om der er wildcard med (*.jeresdomæne.dk), og om certifikatet kan fornyes automatisk.
Et EV-certifikat giver ikke længere virksomhedsnavnet i adresselinjen. Chrome flyttede den oplysning ind bag hængelåsen i version 77 i 2019, så kunderne ser ikke forskel, når de handler.
Med de kortere levetider dækker et betalt årsabonnement flere udstedelser, og hver af dem skal installeres på serveren. Spørg udstederen, om de understøtter ACME (se næste afsnit). Ellers skal I selv skifte certifikatet hver måned fra 2029.
Sådan virker automatisk fornyelse
Automatisk fornyelse foregår næsten altid via ACME, som er den protokol, Let's Encrypt bygger på, og som mange betalte udstedere også understøtter. Et lille program på serveren eller i hostingpanelet, en ACME-klient, beder om et nyt certifikat, beviser kontrol over domænet og installerer det nye certifikat, uden at nogen skal gøre noget.
Forløbet ser sådan ud: Klienten opretter en ordre for de domæner, certifikatet skal dække. Udstederen svarer med en udfordring (challenge) for hvert domæne. Klienten løser udfordringen og beder udstederen om at kontrollere den. Når kontrollen er godkendt, sender klienten en certifikatanmodning (CSR) med den offentlige nøgle, og udstederen returnerer certifikatet. Den private nøgle forlader aldrig serveren.
Der er tre måder at løse udfordringen på, og forskellen betyder noget for, hvad der kan gå galt:
| Metode | Hvordan kontrollen sker | Port | Wildcard | Typisk faldgrube |
|---|---|---|---|---|
| HTTP-01 | Udstederen henter en fil under /.well-known/acme-challenge/ | 80 | Nej | Port 80 er lukket, eller filen rammes af en omdirigering til login |
| DNS-01 | Klienten opretter en TXT-post på _acme-challenge.jeresdomæne.dk | Ingen, kun DNS | Ja | Klienten skal have API-adgang til DNS |
| TLS-ALPN-01 | Kontrollen sker i selve TLS-forbindelsen med en særlig ALPN-protokol | 443 | Nej | Få klienter understøtter den |
HTTP-01 er den mest udbredte. Let's Encrypt følger op til 10 omdirigeringer, men kun til http eller https på port 80 eller 443, så en omdirigering fra http til https er i orden, mens en omdirigering til en anden port eller et login får kontrollen til at fejle. Har I flere webservere bag en load balancer, skal filen kunne hentes fra dem alle.
DNS-01 er den, I skal bruge, når I skal have et wildcard-certifikat som *.eksempel.dk, når serveren ikke kan nås udefra på port 80, eller når der er flere servere, og I ikke vil synkronisere filer mellem dem.
Prisen er, at klienten skal kunne ændre DNS. Let's Encrypt advarer selv om, at det er en risiko at have API-nøgler til DNS liggende på webserveren. To måder at begrænse den på: Brug en API-nøgle, der kun må redigere DNS i den ene zone. Eller lad _acme-challenge.eksempel.dk være en CNAME, der peger over i en separat zone, som kun bruges til udfordringer. Let's Encrypt understøtter at delegere udfordringen med CNAME eller NS på den måde.
Med Certbot og Cloudflare som DNS ser en DNS-01-opsætning sådan ud. Først en fil med en API-token, der kun har rettigheden Zone:DNS:Edit for den zone, certifikatet gælder:
# /root/.secrets/certbot/cloudflare.ini (chmod 600)
dns_cloudflare_api_token = INDSÆT-TOKEN-HERDerefter udstedelsen. Bemærk, at stjerne-domænet skal stå i anførselstegn, så skallen ikke udvider det:
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
--dns-cloudflare-propagation-seconds 60 \
-d eksempel.dk \
-d '*.eksempel.dk'Certbot advarer ved hver kørsel, hvis andre brugere kan læse filen med nøglen, så sæt rettighederne med chmod 600.
Hvornår der skal fornyes, er også ændret. Let's Encrypt anbefaler, at klienten bruger ARI (ACME Renewal Information), hvor udstederen selv fortæller, hvornår der skal fornyes, og at klienten tjekker ARI mindst to gange i døgnet. Kan klienten ikke det, skal den forny, når cirka to tredjedele af levetiden er gået, altså når en tredjedel er tilbage. En fast fornyelse hver 60. dag, som mange opsætninger bruger i dag, holder ikke, når certifikaterne kun gælder 45 dage. Let's Encrypt beder også om, at fornyelsen kører på et tilfældigt tidspunkt i døgnet og ikke præcis kl. 00:00, hvor alle andre gør det.
I praksis falder de fleste webshops i en af disse grupper:
| Opsætning | Hvem fornyer | Det skal I tjekke |
|---|---|---|
| Delt hosting med SSL i kontrolpanelet | Hostingudbyderen | At SSL står til automatisk fornyelse for alle domæner, også www og ekstra domæner |
| Egen server eller VPS | Jer eller jeres udvikler | At ACME-klienten kører, genindlæser webserveren og er opdateret |
| Site bag Cloudflare | Cloudflare (mod kunden) og jer (mod serveren) | At certifikatet på selve serveren også fornyes, hvis Cloudflare kører i Full (strict) |
| Hostet platform, fx en SaaS-webshop | Platformen | At domænet stadig peger korrekt, så platformen kan forny |
| Betalt certifikat købt separat | Jer | Om udstederen tilbyder ACME. Ellers er det manuelt arbejde |
Linjen om Cloudflare kræver en forklaring. Bag Cloudflare er der to TLS-forbindelser: én mellem kunden og Cloudflare og én mellem Cloudflare og jeres server. Cloudflare fornyer selv certifikatet på den første. Kører I i tilstanden Full (strict), kræver Cloudflare, at certifikatet på serveren er gyldigt, ikke udløbet, udstedt af en offentligt betroet udsteder eller af Cloudflares Origin CA, og at domænet står i certifikatet. Udløber certifikatet på serveren, ser kunderne en fejlside fra Cloudflare, selv om hængelåsen mod Cloudflare er i orden.
Certbot på egen server: fornyelse, hooks og prøvekørsel
Certbot er den mest udbredte ACME-klient på Linux-servere. Kører webshoppen på egen server eller VPS, er det her, de fleste fejl opstår, så det er værd at kende de fire kommandoer, der afslører, om fornyelsen faktisk virker.
Først: hvilke certifikater kender Certbot, og hvornår udløber de?
sudo certbot certificatesKommandoen viser hvert certifikat med navn, domæner, udløbsdato og stien til filerne. Certifikaterne ligger under /etc/letsencrypt/live/<navn>/, hvor fullchain.pem er certifikatet med mellemcertifikater, og privkey.pem er den private nøgle. Det er de to filer, webserveren skal pege på.
Dernæst: kører fornyelsen overhovedet? Certbot sætter normalt selv en planlagt opgave op, der kører certbot renew med jævne mellemrum. Den ligger enten som en systemd-timer eller i crontab, afhængigt af hvordan Certbot er installeret:
systemctl list-timers | grep -i certbot
grep -r "certbot" /etc/crontab /etc/cron.d/ 2>/dev/nullGiver ingen af dem et resultat, sker der ingen automatisk fornyelse. Certbots egen dokumentation viser en cron-linje, der kører to gange i døgnet med en tilfældig pause på op til en time, så alle servere ikke rammer udstederen på samme tid:
SLEEPTIME=$(awk 'BEGIN{srand(); print int(rand()*(3600+1))}'); echo "0 0,12 * * * root sleep $SLEEPTIME && certbot renew -q" | sudo tee -a /etc/crontab > /dev/nullcertbot renew fornyer kun de certifikater, der er tæt på at udløbe, så det er ufarligt at køre den ofte. -q fjerner al output undtagen fejl.
Tredje kommando er den vigtigste. En prøvekørsel mod Let's Encrypts testmiljø gennemfører hele forløbet med domænekontrol, men gemmer ikke certifikaterne:
sudo certbot renew --dry-runFejler den her, vil den rigtige fornyelse også fejle. Det typiske svar er en fejl i domænekontrollen, og så er det filen under /.well-known/acme-challenge/, port 80 eller DNS, der skal undersøges. Kør prøvekørslen efter hver ændring af omdirigeringer, firewall, sikkerhedsplugins og DNS.
Fjerde punkt er genindlæsningen. Webserveren læser certifikatet, når den starter, og bruger det fra hukommelsen. Et nyt certifikat på disken gør ingen forskel, før webserveren er genindlæst. Den sikreste løsning er en deploy hook, som Certbot kun kører, når et certifikat faktisk er fornyet. Læg en eksekverbar fil i /etc/letsencrypt/renewal-hooks/deploy/:
#!/bin/sh
# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
# Kører kun efter en vellykket fornyelse. $RENEWED_DOMAINS indeholder de fornyede domæner.
nginx -t && nginx -s reloadsudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.shnginx -t tjekker konfigurationen først, så en fejl i en anden del af konfigurationen ikke tager sitet ned ved genindlæsningen. Bruger I Apache, er det apachectl configtest og en graceful genstart i stedet. Hooks i mappen køres i alfabetisk rækkefølge. Bemærk, at en almindelig --dry-run ikke kører deploy hooks, medmindre I tilføjer --run-deploy-hooks.
Kører I flere tjenester på samme certifikat, fx en mailserver eller en proxy, skal de også genindlæses i hooken. Det er en klassisk fejl, at webserveren får det nye certifikat, mens mailserveren fortsætter med det gamle, indtil den udløber.
Sådan tjekker I jeres certifikater
Start med at finde ud af, hvilke certifikater I har, og hvornår de udløber. Det tager ti minutter og giver et klart billede.
- Åbn jeres site i Chrome, klik på ikonet til venstre for adressen, vælg at forbindelsen er sikker og derefter certifikatet. Her står udstederen og datoen for, hvornår certifikatet udløber.
- Gentag for alle domæner og underdomæner: www, uden www, shop., admin., mail-domæner og gamle kampagnedomæner, der stadig peger på serveren.
- Kør en test på SSL Labs, som viser certifikatkæden, udløbsdato og fejl i opsætningen.
- Søg jeres domæne frem i en database over Certificate Transparency, fx crt.sh. Alle offentligt betroede certifikater bliver logget, så her kan I se, hvilke certifikater der er udstedt til jeres domæner, også dem I har glemt.
Har I mange domæner, er kommandolinjen hurtigere. Den her kommando henter certifikatet fra serveren og viser, hvem det er udstedt til, hvem der har udstedt det, og hvornår det udløber:
openssl s_client -connect www.eksempel.dk:443 -servername www.eksempel.dk </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -enddate -ext subjectAltNameSvaret ser sådan ud:
subject=CN=www.eksempel.dk
issuer=C=US, O=Let's Encrypt, CN=YE2
notAfter=Dec 3 14:34:31 2026 GMT
X509v3 Subject Alternative Name:
DNS:eksempel.dk, DNS:www.eksempel.dk-servername sætter SNI, altså det domænenavn, klienten beder om. Mange servere har flere certifikater på samme IP-adresse og vælger certifikatet ud fra SNI, så uden det kan I få et forkert certifikat at se. notAfter er udløbsdatoen. Listen under Subject Alternative Name viser, hvilke domæner certifikatet dækker, og det er her, I opdager, at shop.eksempel.dk aldrig kom med. -ext findes i OpenSSL 1.1.1 og nyere. På macOS er den indbyggede openssl LibreSSL, som ikke har den, så brug -text i stedet eller installer OpenSSL.
curl giver samme oplysninger og viser samtidig, om certifikatet bliver godkendt:
curl -vI https://www.eksempel.dk 2>&1 | grep -E 'subject:|start date:|expire date:|issuer:|verify|^< HTTP'* subject: CN=www.eksempel.dk
* start date: Sep 4 14:34:32 2026 GMT
* expire date: Dec 3 14:34:31 2026 GMT
* issuer: C=US; O=Let's Encrypt; CN=YE2
* SSL certificate verify ok.
< HTTP/2 200-I henter kun headers, og -v viser TLS-forhandlingen. Linjen SSL certificate verify ok betyder, at kæden er godkendt, og at domænet passer. Står der en fejl i stedet, er det den samme fejl, kunderne får. Hvordan linjerne præcist ser ud, afhænger af, hvilket TLS-bibliotek curl er bygget med.
Ligger sitet bag Cloudflare eller et andet CDN, viser kommandoerne ovenfor kun certifikatet hos CDN'et. For at se certifikatet på selve serveren kan I bede curl om at forbinde direkte til serverens IP-adresse, men stadig sende det rigtige domænenavn. Her er 203.0.113.10 et eksempel på serverens adresse:
curl -svI --resolve www.eksempel.dk:443:203.0.113.10 https://www.eksempel.dk 2>&1 | grep -E 'expire date|verify'--resolve virker som en midlertidig linje i hosts-filen. Det er den hurtigste måde at finde ud af, om det er certifikatet på serveren, der er ved at udløbe, mens alt ser fint ud udefra. Er serveren låst, så den kun tager imod trafik fra Cloudflare, skal kommandoen køres fra et sted, der har adgang.
Let's Encrypt stoppede med at sende mails om udløbende certifikater den 4. juni 2025. Har I regnet med den mail som sikkerhedsnet, er den væk. Overvågning skal derfor ligge hos jer selv eller hos jeres driftspartner, og den bør tjekke certifikatet udefra, præcis som en kunde ser det. Det vender vi tilbage til nedenfor.
CAA-poster og Certificate Transparency
To mekanismer giver jer kontrol over, hvem der må udstede certifikater til jeres domæner, og indsigt i, hvad der faktisk er udstedt. Begge er gratis og tager under en time at sætte op.
En CAA-post er en DNS-post, der fortæller certifikatudstedere, hvem af dem der må udstede til domænet. Udstedere skal tjekke den før udstedelse, og findes der en CAA-post, der ikke nævner dem, må de ikke udstede. Det beskytter mod, at nogen narrer en anden udsteder til at udstede et certifikat til jeres domæne. Et eksempel for en webshop, der bruger Let's Encrypt på serveren:
eksempel.dk. 3600 IN CAA 0 issue "letsencrypt.org"
eksempel.dk. 3600 IN CAA 0 issuewild ";"
eksempel.dk. 3600 IN CAA 0 iodef "mailto:sikkerhed@eksempel.dk"| Felt | Betydning |
|---|---|
0 | Flag. 0 er normalt. 128 markerer posten som kritisk, så en udsteder, der ikke forstår egenskaben, ikke må udstede |
issue | Hvilke udstedere der må udstede almindelige certifikater. letsencrypt.org er Let's Encrypts identifikator |
issuewild | Hvilke udstedere der må udstede wildcard-certifikater. ";" betyder, at ingen må |
iodef | Hvor en udsteder kan sende en rapport om en afvist anmodning |
Udstederen tjekker først det præcise domænenavn og går derefter op gennem de overliggende domæner, indtil den finder en CAA-post. En post på eksempel.dk gælder derfor også for shop.eksempel.dk, medmindre underdomænet har sin egen. Peger et underdomæne med CNAME til en anden tjeneste, følger opslaget CNAME'en, så det er CAA-posten hos målet, der gælder.
Inden I opretter posten, skal I have styr på alle de udstedere, I bruger. Ligger sitet bag Cloudflare, udsteder Cloudflare certifikatet mod kunderne gennem sine egne partnere, og dem skal posten tillade. Bruger I Cloudflares gratis Universal SSL, tilføjer Cloudflare selv CAA-poster for sine udstedere, så snart der findes en CAA-post i zonen. De poster vises ikke i Cloudflares dashboard, men kan ses med et DNS-opslag. Det gælder ikke for Cloudflares betalte Advanced Certificates, hvor I selv skal tillade udstederen. Se, hvad der står i dag:
dig +short CAA eksempel.dkLet's Encrypt understøtter også to udvidelser, der strammer yderligere: accounturi, der kun tillader udstedelse til en bestemt ACME-konto, og validationmethods, der begrænser, hvilke kontrolmetoder udstederen må bruge. Med accounturi kan en angriber, der midlertidigt overtager domænet, ikke få udstedt et certifikat uden jeres kontonøgle:
eksempel.dk. 3600 IN CAA 0 issue "letsencrypt.org;validationmethods=dns-01"Certificate Transparency (CT) er den anden halvdel. Alle offentligt betroede certifikater bliver skrevet i offentlige logs, som alle kan søge i. På crt.sh kan I søge med % som jokertegn for at se alle certifikater til domænet og dets underdomæner, fx %.eksempel.dk. Der findes også en JSON-udgave, som er praktisk i et script:
curl -s 'https://crt.sh/?q=%25.eksempel.dk&exclude=expired&output=json' | jq -r '.[].name_value' | sort -u%25 er % kodet til en URL, exclude=expired udelader udløbne certifikater, og jq trækker domænenavnene ud. Kig efter to ting, når I gennemgår resultatet på crt.sh: certifikater fra udstedere, I ikke bruger, og underdomæner, I havde glemt. Et certifikat, I ikke kan forklare, kan betyde, at nogen har haft kontrol over jeres DNS eller en af jeres servere. crt.sh er en gratis tjeneste og svarer ikke altid, så den egner sig til stikprøver, ikke som eneste overvågning.
Bruger I Cloudflare, kan I i stedet slå Certificate Transparency Monitoring til under SSL/TLS og Edge Certificates og tilføje en mailadresse. Så får I en mail, hver gang en udsteder logger et certifikat til jeres domæne. Cloudflares egne certifikater er filtreret fra, så det, der kommer, er det, I skal se på.
Overvågning af udløbsdatoen
Et certifikat skal overvåges udefra, fordi det er den eneste måde at se det samme som kunden. En overvågning, der læser filen på serveren, opdager ikke, at webserveren aldrig blev genindlæst, eller at Cloudflare viser et andet certifikat.
Den nemmeste løsning er en uptime-tjeneste, der også tjekker certifikatets udløbsdato. De fleste kan sende en alarm et antal dage før. Sæt den til mindst 14 dage. Med 47 dages levetid og fornyelse ved to tredjedele er der cirka 16 dage tilbage, når fornyelsen skal ske, så en alarm ved 14 dage betyder, at mindst én fornyelse er gået galt.
Har I en server, der allerede kører cron, kan et lille script gøre det samme. Scriptet skriver kun noget ud, når der er et problem, så cron kun sender en mail, når der er brug for den:
#!/usr/bin/env bash
# /usr/local/bin/tjek-cert.sh
# Skriver kun noget ud, hvis et certifikat mangler eller udløber inden for 14 dage
GRAENSE=$((14 * 86400))
STATUS=0
for host in eksempel.dk www.eksempel.dk shop.eksempel.dk; do
pem=$(timeout 10 openssl s_client -connect "$host:443" -servername "$host" </dev/null 2>/dev/null | openssl x509 2>/dev/null)
if [ -z "$pem" ]; then
echo "FEJL: intet certifikat fra $host"
STATUS=2
continue
fi
if ! printf '%s\n' "$pem" | openssl x509 -noout -checkend "$GRAENSE" >/dev/null; then
echo "ADVARSEL: $host $(printf '%s\n' "$pem" | openssl x509 -noout -enddate)"
STATUS=1
fi
done
exit $STATUS-checkend tager et antal sekunder og afslutter med en fejlkode, hvis certifikatet udløber inden for den periode. Det er derfor, scriptet ikke behøver at regne med datoer, og det virker ens på alle systemer. timeout 10 sørger for, at et domæne, der ikke svarer, ikke får scriptet til at hænge. Et domæne, der slet ikke svarer på 443, giver linjen FEJL, og det er værd at vide i sig selv.
Så skal scriptet køre hver morgen og sende output til en mailadresse, der bliver læst. MAILTO er cron's egen indstilling for, hvor output sendes hen, og kræver, at serveren kan sende mail:
# crontab -e
MAILTO=drift@eksempel.dk
17 7 * * * /usr/local/bin/tjek-cert.shUanset om I bruger en tjeneste eller et script, så lad listen af domæner komme fra den oversigt, I lavede i forrige afsnit, og ikke fra hukommelsen. Og læg overvågningen et andet sted end på den server, den overvåger. Vi har en side om, hvordan vi sætter overvågning og alarmer op, så I får besked, før certifikatet udløber, og ikke når kunderne skriver.
Det går galt, når certifikatet udløber
Når et certifikat udløber, viser browseren en helsides advarsel med teksten "Din forbindelse er ikke privat" i Chrome, ofte med fejlkoden NET::ERR_CERT_DATE_INVALID. Det er det sidste, en kunde skal se, før de skal taste kortoplysninger. De fleste lukker fanen, og annoncer og nyhedsbreve sender trafik ind i en blindgyde, indtil det er rettet.
De fejl, der typisk fører til et udløbet certifikat, og hvordan I finder dem:
| Fejl | Sådan ser det ud | Sådan finder I den |
|---|---|---|
| Fornyelsen kører, men webserveren bliver ikke genindlæst | certbot certificates viser en ny dato, men browseren viser den gamle | Sammenlign notAfter fra openssl s_client med filen på disken |
| Domænekontrollen fejler | Prøvekørslen fejler med en fejl om autorisation | certbot renew --dry-run og en test af /.well-known/acme-challenge/ |
| DNS er flyttet | Certifikatet skulle fornyes på en server, som domænet ikke længere peger på | dig +short A eksempel.dk og sammenlign med serverens adresse |
| Manuelt certifikat, som én person havde ansvaret for | Personen er stoppet, eller mailen om fornyelse røg i spam | Udstederen i certifikatet er ikke den, I troede |
| Underdomæner bliver glemt | Forsiden virker, men shop. eller et betalingsdomæne udløber | crt.sh og SAN-listen i certifikatet |
| API-integrationer og interne systemer | Lagerstyring, ERP eller fragt stopper, selv om shoppen ser fin ud | Fejllog hos integrationen |
| Certifikatet er fastlåst i en app eller enhed | Systemet går i stå ved hver udskiftning | Leverandøren af systemet |
Fejlen i domænekontrollen er den sværeste at opdage, fordi den ofte skyldes noget, der er ændret længe før. En ny regel om at sende alle ukendte stier til en login-side, en sikkerhedsplugin, der blokerer anmodninger fra udlandet, eller en firewall, der lukker port 80, fordi alt alligevel kører på https. Test det sådan:
curl -sI http://eksempel.dk/.well-known/acme-challenge/testDet forventede svar er en 404 fra jeres egen webserver eller en omdirigering til https på samme domæne. Får I en omdirigering til en login-side eller en anden port, en 403 fra en sikkerhedsplugin eller slet intet svar, så er det den, der får fornyelsen til at fejle. For webservere som nginx kan stien undtages fra omdirigeringer med en separat location /.well-known/acme-challenge/ før de andre regler.
Et udløbet certifikat er ikke et hackerangreb, men det kan ligne et for kunderne. Er certifikatet skiftet ud uden jeres viden, eller peger domænet pludselig et andet sted hen, er det en anden sag. Så kig på vores side om hacket domæne og DNS.
Tjekliste før marts 2027
Brug listen her inden 15. marts 2027, hvor levetiden falder til 100 dage:
- Lav en oversigt over alle domæner og underdomæner med certifikat, hvem der udsteder dem, og hvornår de udløber. Brug crt.sh til at finde dem, I har glemt.
- Bekræft for hvert certifikat, at fornyelsen er automatisk. Er den ikke det, så flyt til en udsteder eller hosting, der kan automatisere.
- Tjek, at ACME-klienten er opdateret, understøtter ARI og ikke fornyer på en fast 60-dages plan.
- Test en fornyelse nu med
certbot renew --dry-runeller tilsvarende i jeres klient, i stedet for at vente på, at den rigtige fornyelse fejler. - Sørg for, at webserveren og andre tjenester på samme certifikat genindlæses automatisk efter fornyelsen, fx med en deploy hook.
- Tjek, at
/.well-known/acme-challenge/ikke blokeres af omdirigeringer, firewall eller sikkerhedsplugins. - Brug DNS-01 med en begrænset API-nøgle, hvis I har wildcard-certifikater eller servere, der ikke kan nås på port 80.
- Kører I bag Cloudflare, så tjek både certifikatet mod kunden og certifikatet på serveren med
curl --resolve. - Opret CAA-poster, der kun tillader de udstedere, I faktisk bruger.
- Find integrationer og apps, der forbinder til shoppen, og tjek, at de ikke har låst sig til et bestemt certifikat.
- Sæt overvågning op, der tjekker udløbsdatoen udefra og giver besked mindst to uger før.
- Skriv ned, hvem der har ansvaret, og hvem der har adgang til DNS, hosting og certifikatkonto.
Kører shoppen på egen server, hører certifikaterne med i den almindelige drift sammen med opdateringer og backup. Har I mistanke om, at serveren er kompromitteret, så læs vores side om hacket server og hosting.
Spørgsmål og svar
Skal vi gøre noget, hvis vi har et gratis SSL-certifikat fra hostingen? Som regel ikke andet end at tjekke, at fornyelsen faktisk er automatisk, og at alle domæner er med. Hostingudbyderen håndterer de nye levetider, men det skader ikke at spørge.
Hvad sker der med et certifikat, vi lige har købt for et år? Et certifikat, der er udstedt før en skæringsdato, gælder sin levetid ud. Fra 15. marts 2026 kan et nyt certifikat højst gælde 200 dage, så et års abonnement vil i praksis give mindst to udstedelser.
Hvor ofte skal certifikatet fornyes i 2029? Med 47 dages levetid og fornyelse ved to tredjedele af levetiden bliver det cirka hver måned. Med Let's Encrypts 45 dage fra februar 2028 er det samme rytme.
Skal vi bruge HTTP-01 eller DNS-01? HTTP-01, hvis I har én webserver, der kan nås på port 80, og ikke skal bruge wildcard. DNS-01, hvis I skal bruge wildcard, har flere servere eller servere, der ikke kan nås udefra. Ved DNS-01 skal API-nøglen begrænses til den ene zone.
Kan en CAA-post stoppe vores fornyelse? Ja, hvis den ikke nævner den udsteder, der fornyer. Det er den mest almindelige fejl, når man opretter CAA-poster. Kør derfor en prøvekørsel, og tjek Cloudflare eller hostingens certifikat, efter at posten er oprettet.
Påvirker et udløbet certifikat Google-placeringer? Google har ikke en offentlig regel om udløbne certifikater i søgeresultaterne, som vi har kunnet finde. Men kunder, der klikker ind fra Google, møder advarslen og forlader siden, og det er nok i sig selv.
Hvad det betyder for en webshop
For en webshop er det her ikke et sikkerhedshul, der skal lukkes i dag. Det er en driftsopgave, der skal være løst, før levetiden falder til 100 dage i marts 2027. Har I allerede automatisk fornyelse via hosting eller Cloudflare, er der sandsynligvis ikke meget at gøre ud over at tjekke underdomæner, certifikatet på serveren og integrationer. Har I et betalt certifikat, som nogen fornyer i hånden, skal det ændres.
Det dyre scenarie er et udløbet certifikat på en fredag aften i november. Advarslen rammer alle kunder på én gang, annoncebudgettet kører videre, og det tager typisk længere tid at få styr på en fejlet fornyelse, når man ikke har prøvet det før. En prøvekørsel i dag og en alarm 14 dage før udløb fjerner det meste af den risiko.
Vil I have os til at gennemgå jeres certifikater, domæner og fornyelse, så skriv til os. Vi kan også sætte overvågning og alarmer op, så I får besked, før noget udløber, og tage hele driften af serveren som en del af en sikkerhedsaftale.
Kilder
- CA/Browser Forum, Ballot SC-081v3
- DigiCert: TLS certificate lifetimes will officially reduce to 47 days
- Let's Encrypt: Decreasing certificate lifetimes to 45 days
- Let's Encrypt: Certificate lifetime rationale
- Let's Encrypt: Profiles
- Let's Encrypt: Challenge types
- Let's Encrypt: Integration guide
- Let's Encrypt: CAA
- Let's Encrypt FAQ
- Let's Encrypt: Ending expiration emails
- Certbot User Guide
- certbot-dns-cloudflare
- RFC 8659: DNS Certification Authority Authorization
- OpenSSL: openssl-x509
- OpenSSL: openssl-s_client
- curl man page
- Cloudflare: Universal SSL
- Cloudflare: Full (strict)
- Cloudflare: CAA records
- Cloudflare: Certificate Transparency Monitoring
- Chromium: EV UI moving to page info
- Google Chrome Hjælp om fejlmeddelelser
Relaterede artikler om Sikkerhed
Læs også
01 Er min mail hacket? Tegnene og de første skridt for jeres firmamail 02 Flere konverteringer i Meta fra 12. november: hvad der ændrer sig, og hvad I skal tjekke 03 Meta slår product browsing til i jeres annoncer den 28. oktober
