automatisch certificaat
Een verlopen certificaat kost je geen data, geen uptime en geen klanten — het kost je een browserwaarschuwing die elke bezoeker drie klikken diep laat nadenken over of ze je site nog vertrouwen. Dit artikel laat zien hoe je TLS-certificaten automatisch laat uitgeven en vernieuwen met het ACME-protocol, op een Linux-server met Certbot en Let's Encrypt. Je hebt root of sudo nodig, een publiek bereikbare webserver en een domeinnaam waarvan je de DNS beheert.
Vereisten
- Een Linux-server, Debian 12 of Ubuntu 24.04 LTS. Andere distributies werken ook, maar de package-namen verschillen.
- Nginx 1.24 of Apache 2.4 als webserver.
- Een A-record dat naar het IP-adres van je server wijst. Zonder dat kan Let's Encrypt je domein niet valideren.
- Poort 80 en 443 open in je firewall. De HTTP-01 challenge loopt over poort 80, ook als je site alleen HTTPS draait.
- Python 3.11 of hoger, meegeleverd met beide distributies.
Stappen
1. Installeer Certbot
Certbot is de reference client voor Let's Encrypt. Er zijn alternatieven — acme.sh, lego, of de ingebouwde ACME-support van Caddy en Traefik — maar Certbot heeft de breedste documentatie en de meeste package-support.```bash sudo apt update sudo apt install -y certbot python3-certbot-nginx ```
Voor Apache gebruik je `python3-certbot-apache` in plaats van de nginx-plugin. De plugin zorgt ervoor dat Certbot je webserverconfig zelf aanpast: het certificaat wordt geïnstalleerd, de TLS-blokken worden toegevoegd en de HTTP-redirect naar HTTPS wordt ingesteld.
2. Controleer of je domein resolveert
Voordat je iets aanvraagt, wil je weten dat de buitenwereld je server kan vinden. Een verkeerd A-record is de meest voorkomende reden dat een certificaataanvraag faalt.```bash dig +short example.com A ```
Het antwoord moet het publieke IP-adres van je server zijn. Krijg je niets terug, wacht dan op DNS-propagatie. Dat kan minutes duren, soms uren, afhankelijk van je TTL.
3. Vraag het eerste certificaat aan
Nu de eigenlijke aanvraag. Certbot doet drie dingen in één commando: het vraagt een certificaat aan bij Let's Encrypt, valideert je domein via een HTTP-01 challenge, en installeert het resultaat in je webserver.```bash sudo certbot --nginx -d example.com -d www.example.com ```
Certbot plaatst een tijdelijk bestand onder `/.well-known/acme-challenge/` op je webserver. Let's Encrypt haalt dat op via poort 80 en weet daarmee dat jij de controle over het domein hebt. Je krijgt een e-mailadres te kiezen voor vervalwaarschuwingen en een keuze of je HTTP automatisch naar HTTPS wilt laten redirecten. Zeg ja tegen die redirect; er is geen goede reden om plaintext HTTP te blijven serveren.
Wil je alleen een certificaat zonder dat Certbot je config aanraakt, gebruik dan `certonly` in plaats van de plugin-modus. Dan moet je de TLS-instellingen zelf in je webserver zetten. Meer werk, meer controle.
4. Begrijp de geldigheidsduur
Let's Encrypt-certificaten zijn 90 dagen geldig. Dat is kort, en dat is bewust: korte looptijden beperken de schade als een private key uitlekt, en ze dwingen automatisering af. Een certificaat dat je handmatig moet vernieuwen, is een certificaat dat je een keer vergeet.Die 90 dagen zijn geen probleem zolang de vernieuwing automatisch loopt. Ze zijn een groot probleem als je het in je agenda hebt gezet.
5. Stel automatische vernieuwing in
Certbot installeert bij de package-installatie een systemd timer die twee keer per dag draait. Die timer voert `certbot renew` uit, en dat commando vernieuwt alleen certificaten die binnen 30 dagen verlopen. Je hoeft hier niets voor te doen, maar je moet wel controleren dat de timer actief is.```bash systemctl list-timers | grep certbot ```
Zie je `certbot.timer` met een volgende uitvoeringstijd, dan loopt het. Zie je niets, dan is de timer niet geïnstalleerd of uitgeschakeld — op oudere systemen of in containers gebeurt dat.
Op systemen zonder systemd, zoals Alpine of een minimale container, zet je een cronjob neer:
```bash echo "0 3,15 * root certbot renew --quiet" | sudo tee /etc/cron.d/certbot-renew ```
Twee keer per dag op vaste tijden, met een willekeurige vertraging ingebouwd door Certbot zelf zodat niet iedereen tegelijk bij Let's Encrypt aanklopt.
6. Test de vernieuwing zonder iets te vernieuwen
Dit is de stap die mensen overslaan en waar het later misgaat. Met `--dry-run` doorloopt Certbot het hele vernieuwingsproces tegen de staging-omgeving van Let's Encrypt, zonder je echte certificaten aan te raken.```bash sudo certbot renew --dry-run ```
Faalt deze test, dan faalt de echte vernieuwing over een paar weken ook. Beter dat je het nu weet dan op een zondagavond als je certificaat nog drie dagen geldig is.
7. Kies je validatiemethode
De HTTP-01 challenge werkt voor de meeste setups, maar heeft één beperking: je webserver moet publiek op poort 80 bereikbaar zijn. Draai je achter een CDN, een load balancer, of heb je alleen interne services, dan heb je DNS-01 nodig.Bij DNS-01 zet Certbot een TXT-record neer in je DNS-zone. Dat werkt ook voor wildcard-certificaten (`*.example.com`), wat met HTTP-01 niet kan. De prijs: je moet een DNS-provider hebben met een API, en je geeft Certbot credentials om je DNS te wijzigen.
```bash sudo certbot certonly \ --dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \ -d example.com -d "*.example.com" ```
Het credentials-bestand bevat je Cloudflare API-token en moet `chmod 600` hebben. Iedereen die dat bestand leest, kan je DNS aanpassen.
8. Herlaad je webserver na vernieuwing
Certbot herlaadt Nginx of Apache meestal zelf na een geslaagde vernieuwing, via een hook die de plugin installeert. Gebruik je een andere webserver of een container, dan moet je dat zelf regelen met een deploy-hook.```bash sudo certbot renew --deploy-hook "systemctl reload nginx" ```
Zonder reload blijft de oude, verlopen certificaatversie in het geheugen van het proces staan. De bestanden op schijf zijn dan vernieuwd, maar je server serveert nog steeds het oude spul. Dat is precies het soort fout dat je pas opmerkt als een bezoeker klaagt.
Verificatie
Controleer eerst wat Certbot zelf vindt van je certificaten:```bash sudo certbot certificates ```
Je krijgt per certificaat de domeinen, de vervaldatum en het pad naar de bestanden. Staat de vervaldatum verder dan 30 dagen in de toekomst en heb je net een `--dry-run` zien slagen, dan is het goed.
Daarna de echte test: wat serveert je server naar buiten?
```bash echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \ | openssl x509 -noout -subject -dates ```
Je ziet het subject en de `notBefore`/`notAfter` datums. Vergelijk die met wat `certbot certificates` zegt. Wijkt het af, dan serveert je webserver een ander certificaat dan Certbot heeft geïnstalleerd — meestal een configuratieprobleem, geen certificaatprobleem.
Veelgestelde problemen
De HTTP-01 challenge faalt met een 404 of een timeout. Meestal blokkeert een firewall poort 80, of je DNS wijst nog naar een oude server. Test met `curl -I http://example.com/.well-known/acme-challenge/test` of je webserver die map überhaupt bereikbaar maakt. Een redirect naar HTTPS in je webserverconfig voordat Certbot het certificaat heeft, breekt de challenge ook — Let's Encrypt volgt geen redirects naar een ongeldig certificaat.Rate limit bij Let's Encrypt. Je mag per geregistreerd domein maximaal 50 certificaten per week aanvragen, en er is een limiet van 5 mislukte validaties per uur per account. Raak je die, dan zit je uren vast. Gebruik tijdens het testen altijd `--dry-run` of `--staging`; de staging-omgeving heeft veel ruimere limieten en levert certificaten die je browser niet vertrouwt, wat precies de bedoeling is.
De vernieuwing loopt wel, maar de webserver pikt het niet op. Dit gebeurt als je een deploy-hook mist of als je webserver in een container draait die het certificaat als volume heeft gemount zonder herstart. Zet een expliciete reload-hook neer, of mount het certificaat als een secret dat je orchestrator opnieuw inleest.
Automatisering haalt de mens uit de lus, maar niet uit de verantwoordelijkheid. Er blijft één iemand nodig die de dry-run leest en de timer in de gaten houdt. Die iemand ben jij, tenzij je een monitoring-check op de vervaldatum zet.