Module 7 · 7.3
https met Let's Encrypt
Module 7: Domein, webserver en https · Leestijd: 12 minuten
Leerdoel: Na deze les kun je met certbot een gratis certificaat van Let's Encrypt aanvragen voor nginx, http naar https laten doorsturen, het automatisch vernieuwen controleren en de meest voorkomende fouten bij een aanvraag oplossen.
Kernbegrippen: certificaat, certificaatuitgever (CA), ACME, Let's Encrypt, domeinvalidatie, HTTP-01, DNS-01, TLS-ALPN-01, certbot, vernieuwen, certbot renew --dry-run, looptijd, ARI, rate limits, staging, CAA, doorsturen naar https
Waarom https, en wat een certificaat bewijst
Zonder https gaat alles tussen browser en server onversleuteld over het netwerk: wachtwoorden, formulieren, cookies. Iedereen onderweg (een openbare wifi, een gehackte router) kan meelezen of iets veranderen. Browsers markeren http-sites daarom als "niet veilig", en sommige functies werken alleen via https. Voor een kluis als Vaultwarden (les 9.4) is https zelfs verplicht.
https gebruikt TLS, en daarvoor heeft je server een certificaat nodig: een bewijs, ondertekend door een certificaatuitgever (CA) die browsers vertrouwen, dat deze sleutel bij deze naam hoort. Een gewoon certificaat bewijst alleen dat de aanvrager de domeinnaam beheert (domeinvalidatie). Het zegt niets over wie je bent of of je betrouwbaar bent.
Let's Encrypt is een gratis CA die alleen domeingevalideerde certificaten uitgeeft, volledig automatisch via het ACME-protocol. Een programma op je server (de ACME-client) vraagt het certificaat aan, bewijst dat het de naam beheert, installeert het en vernieuwt het op tijd. Deze les gebruikt certbot, de client van de EFF. Caddy (les 7.4) heeft een ACME-client ingebouwd.
Hoe bewijs je dat je de naam beheert?
Let's Encrypt kent drie soorten uitdagingen (challenges):
| Uitdaging | Hoe | Poort | Wildcard (*.example.com) |
|---|---|---|---|
| HTTP-01 | een bestand onder http://<naam>/.well-known/acme-challenge/ neerzetten | 80 | nee |
| DNS-01 | een TXT-record _acme-challenge.<naam> zetten | geen | ja |
| TLS-ALPN-01 | een speciaal certificaat tonen tijdens de TLS-handshake | 443 | nee |
Voor een gewone VPS met een website is HTTP-01 het eenvoudigst. Daarvoor moet:
- de naam met A (en AAAA) naar je server wijzen (les 7.1);
- poort 80 open zijn voor de hele wereld, ook als je site verder alleen https gebruikt. Let's Encrypt valideert alleen via poort 80 en vanaf meerdere plekken op internet; je kunt die adressen niet in je firewall zetten;
- je server via IPv4 én IPv6 hetzelfde antwoorden. Heeft de naam een AAAA-record, dan probeert Let's Encrypt eerst IPv6. Alleen als IPv6 helemaal geen verbinding geeft, valt het terug op IPv4.
DNS-01 heb je nodig voor een wildcardcertificaat, of als de server niet van buiten bereikbaar is. Dan moet de ACME-client je DNS kunnen aanpassen, meestal via een API-sleutel van je DNS-aanbieder. Die sleutel kan je hele DNS wijzigen: bewaar hem net zo zorgvuldig als een wachtwoord.
certbot installeren
De makers van certbot raden de snap aan, omdat die altijd de nieuwste versie heeft. Op Debian en Ubuntu kan het ook gewoon uit de pakketbron:
anna@web1:~$ sudo apt install certbot python3-certbot-nginxDe versie uit de distributie is ouder maar krijgt beveiligingsupdates via apt (les 4.1 en 4.2), en dat past bij de rest van deze cursus. Kies één van de twee, niet allebei: twee installaties zitten elkaar bij het vernieuwen in de weg.
Een certificaat aanvragen
Met de site uit les 7.2 al werkend op poort 80:
anna@web1:~$ sudo certbot --nginx -d example.com -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address or hit Enter to skip.
(Enter 'c' to cancel):
...
Requesting a certificate for example.com and www.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2027-02-07.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for example.com to /etc/nginx/sites-enabled/example.com
Successfully deployed certificate for www.example.com to /etc/nginx/sites-enabled/example.com
Congratulations! You have successfully enabled HTTPS on https://example.com and https://www.example.com(Datum en details zijn een voorbeeld.) De plug-in --nginx doet drie dingen: hij zet tijdelijk de challenge klaar, haalt het certificaat op, en past je server block aan met een listen 443 ssl-blok en een doorverwijzing van http naar https. Wil je dat liever zelf doen, gebruik dan certbot certonly --nginx en zet de regels zelf in je configuratie.
Een paar dingen om op te letten:
- Vraag alle namen in één keer aan die bij de site horen (
-dper naam). Elke naam moet naar de server wijzen, anders mislukt de hele aanvraag. - De privésleutel (
privkey.pem) staat in/etc/letsencrypt/live/en is alleen voor root leesbaar. Kopieer hem niet naar andere plekken en zet hem nooit in een back-up die anderen kunnen lezen. - Het mailadres is optioneel. Let's Encrypt stuurt sinds juni 2025 geen mails meer als een certificaat bijna verloopt. Je moet dus zelf bewaken dat vernieuwen lukt (les 8.3).
http naar https doorsturen
Na certbot ziet je configuratie er ongeveer zo uit (opgeschoond; certbot zet er zelf commentaar # managed by Certbot en soms if-regels bij):
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
root /var/www/example.com;
...
}Het eerste blok stuurt alles via http door naar dezelfde naam en hetzelfde pad via https, met een permanente doorverwijzing (301). Het challengebestand voor het vernieuwen werkt nog steeds: Let's Encrypt volgt die doorverwijzing. Het tweede blok is de echte site. Wil je ook nog www naar de kale naam sturen (of andersom), doe dat dan in een eigen blok, zodat bezoekers één vaste naam zien.
Vernieuwen: automatisch, en controleren
Een certificaat van Let's Encrypt is nu 90 dagen geldig. Dat wordt korter: Let's Encrypt heeft aangekondigd dat het standaardprofiel vanaf 10 februari 2027 certificaten van 64 dagen uitgeeft en vanaf 16 februari 2028 van 45 dagen. Met de hand vernieuwen is dus geen optie; het moet automatisch.
certbot zet bij de installatie een systemd-timer (of een cronregel) neer die twee keer per dag kijkt of een certificaat vernieuwd moet worden. Controleer dat die er staat, en test het vernieuwen met een proefaanvraag:
anna@web1:~$ systemctl list-timers 'certbot*'
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-11-09 22:41:00 CET 9h left - - certbot.timer certbot.service
anna@web1:~$ sudo certbot renew --dry-run
...
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)Na het vernieuwen moet nginx het nieuwe certificaat ook laden. Met de nginx-plug-in regelt certbot dat zelf; gebruik je certonly, zet dan een deploy hook neer die nginx herlaadt, bijvoorbeeld een uitvoerbaar script in /etc/letsencrypt/renewal-hooks/deploy/ met systemctl reload nginx.
Goede ACME-clients gebruiken ARI (ACME Renewal Information): Let's Encrypt zegt dan zelf wanneer een certificaat vernieuwd moet worden, bijvoorbeeld eerder als er iets mis is met een reeks certificaten. Houd je client daarom up-to-date.
Als een aanvraag mislukt
| Melding (ingekort) | Oorzaak | Oplossing |
|---|---|---|
Timeout during connect (likely firewall problem) | poort 80 dicht, of de naam wijst naar een ander adres | firewall (les 5.2), A/AAAA (les 7.1) |
Invalid response from http://.../.well-known/acme-challenge/...: 404 | een andere server of ander server block antwoordt, vaak via IPv6 | listen [::]:80, AAAA-record nakijken |
CAA record for example.com prevents issuance | een CAA-record staat alleen een andere uitgever toe | CAA aanpassen (les 7.1) |
too many certificates already issued | een rate limit | wachten; testen met staging |
Let's Encrypt heeft rate limits om misbruik te voorkomen. De belangrijkste: hoogstens 50 nieuwe certificaten per geregistreerd domein per 7 dagen, hoogstens 5 certificaten voor precies dezelfde set namen per 7 dagen, en hoogstens 5 mislukte validaties per naam per uur. Wie aan het proberen is en het steeds opnieuw aanvraagt, loopt daar snel tegenaan. Test daarom met de staging-omgeving, die veel ruimere grenzen heeft maar certificaten geeft die browsers niet vertrouwen:
anna@web1:~$ sudo certbot certonly --nginx --staging -d test.example.comWerkt het daar, vraag dan het echte certificaat aan.
Op AlmaLinux en Rocky Linux
certbot komt daar uit EPEL (dnf install certbot python3-certbot-nginx) of als snap. De plug-in en de commando's zijn hetzelfde. Denk aan firewalld (--add-service=http --add-service=https) en aan SELinux als certificaten op een ongebruikelijke plek staan.
In de praktijk
Bij een hostingpakket regelt het paneel het certificaat voor je (bij WebOké en bij andere hostingbedrijven met DirectAdmin, cPanel of Plesk). Op een VPS doe je het zelf, met certbot, Caddy of de ACME-client die bij je software hoort. Dat geldt bij elke aanbieder.
Samenvatting
- Een certificaat van Let's Encrypt bewijst dat je de naam beheert; certbot vraagt het aan, installeert en vernieuwt het via ACME.
- HTTP-01 heeft poort 80 open nodig, voor iedereen, en hetzelfde antwoord via IPv4 en IPv6; DNS-01 is voor wildcards.
certbot --nginx -d ... -d ...regelt certificaat en doorsturen naar https; vraag alle namen van een site in één keer aan.- Certificaten zijn nu 90 dagen geldig en worden korter; controleer de timer en
certbot renew --dry-run, en bewaak zelf de vervaldatum. - Test met
--stagingom rate limits te vermijden; let op CAA.
Quiz
Opdracht
Opdracht Z7.3: https met een geldig certificaat. Vraag voor je site een certificaat aan (met certbot of Caddy), stuur http door naar https en test het vernieuwen met certbot renew --dry-run (bij Caddy: kijk in de logs of het certificaat is opgehaald). Vul de naam van je site in. Het programma maakt een TLS-verbinding naar poort 443 en controleert of het certificaat geldig is, door een vertrouwde uitgever is ondertekend en je naam dekt, en vraagt daarna http://<naam>/ op om te zien of je doorstuurt naar https. Daarnaast vul je in wanneer je certificaat verloopt en hoe het vernieuwen bij jou geregeld is.
Verder lezen
- SSL-certificaat activeren, vernieuwen en problemen oplossen
- Gratis DNS-cursus 5.2: CAA: wie mag certificaten uitgeven?
- Let's Encrypt, Challenge Types: https://letsencrypt.org/docs/challenge-types/
- Let's Encrypt, Rate Limits: https://letsencrypt.org/docs/rate-limits/
- Let's Encrypt, Decreasing Certificate Lifetimes to 45 Days: https://letsencrypt.org/2025/12/02/from-90-to-45
- Certbot-instructies (nginx): https://certbot.eff.org/instructions?ws=nginx&os=snap
