Let's Encrypt SSL/TLS instellen voor Nginx op Debian 12 en Ubuntu 24.04

11 min leestijd·Matthieu|

Verkrijg en verleng automatisch gratis TLS-certificaten met Certbot voor Nginx op Debian 12 of Ubuntu 24.04. Behandelt DNS-configuratie, Certbot-installatie, HTTP-naar-HTTPS-redirect, TLS-hardening, HTTP/2, HSTS en het stoppen van OCSP.

Let's Encrypt SSL/TLS instellen voor Nginx op Debian 12 en Ubuntu 24.04

Deze tutorial loodst je door het verkrijgen van een gratis TLS-certificaat van Let's Encrypt met Certbot, het configureren van Nginx voor HTTPS en het instellen van automatische verlenging. Elke stap bevat een verificatiecommando zodat je kunt bevestigen wat er is gebeurd voordat je verdergaat.

Als je Nginx nog niet hebt geinstalleerd, begin dan met Nginx installeren op Debian 12 en Ubuntu 24.04. Voor het grotere plaatje van Nginx-beheer op een VPS, zie Nginx-beheer op een VPS.

Wat heb je nodig voordat je een certificaat aanvraagt?

Voordat Certbot een certificaat kan uitgeven, moet je domein naar het IP-adres van je server wijzen en moet Nginx draaien met een server block voor dat domein. Let's Encrypt valideert domeineigendom door een HTTP-verzoek naar je server te sturen. Als DNS niet naar je VPS verwijst of Nginx niet luistert, mislukt de challenge.

Je hebt nodig:

  • Een VPS met Debian 12 of Ubuntu 24.04 waarop Nginx is geinstalleerd vanuit de officiele repository (Nginx installeren op Debian 12 en Ubuntu 24.04)
  • Een geregistreerde domeinnaam (we gebruiken example.com als voorbeeld)
  • Een A-record dat example.com naar het IPv4-adres van je server wijst
  • Een AAAA-record dat naar je IPv6-adres wijst (als je server er een heeft)
  • Poort 80 open in je firewall (Certbot gebruikt HTTP-01 challenges)
  • Een werkend Nginx server block voor je domein (Nginx Server Blocks)

DNS-records instellen

Maak een A-record aan bij je DNS-provider:

Type Naam Waarde TTL
A example.com 203.0.113.10 300
AAAA example.com 2001:db8::1 300

Vervang de IP-adressen door de daadwerkelijke adressen van je server. Stel de TTL laag in (300 seconden) tijdens het opzetten, zodat wijzigingen snel propageren. Je kunt dit later verhogen.

DNS-resolutie verifieren

Wacht een paar minuten na het aanmaken van de records en verifieer vervolgens vanaf je lokale machine (niet de server):

dig +short example.com A
dig +short example.com AAAA

Je zou de IP-adressen van je server in de output moeten zien. Als je niets ziet of een ander IP, is het record nog niet gepropageerd. Wacht en probeer opnieuw.

Verifieer dat Nginx reageert op poort 80 vanaf je lokale machine:

curl -I http://example.com

Je zou een HTTP/1.1 200 OK respons moeten krijgen met Server: nginx. Als de verbinding een time-out geeft, controleer dan je firewallregels.

Hoe installeer je Certbot op Debian 12 en Ubuntu 24.04?

Installeer Certbot en de Nginx-plugin vanuit de pakketrepository van je distributie met apt. De Nginx-plugin laat Certbot automatisch je server blocks aanpassen om TLS in te schakelen.

sudo apt update
sudo apt install certbot python3-certbot-nginx -y

Verifieer de installatie:

certbot --version

Op Debian 12 installeert dit Certbot 2.1.0. Op Ubuntu 24.04 krijg je Certbot 2.9.0. Beide versies werken voor alles in deze tutorial.

Let op: als je Nginx hebt geinstalleerd vanuit de officiele nginx.org-repository (zoals aanbevolen in Nginx installeren op Debian 12 en Ubuntu 24.04), werkt de Certbot Nginx-plugin zonder extra configuratie. De plugin detecteert server blocks in /etc/nginx/conf.d/ en /etc/nginx/sites-enabled/.

Hoe verkrijg je een Let's Encrypt-certificaat voor Nginx?

Voer certbot --nginx uit met je domeinnaam. Certbot neemt contact op met Let's Encrypt, bewijst dat jij het domein beheert via een HTTP-01 challenge, verkrijgt het certificaat en bewerkt je Nginx server block om het te gebruiken. Het hele proces duurt ongeveer 30 seconden.

sudo certbot --nginx -d example.com -d www.example.com

Certbot vraagt om je e-mailadres (voor verlengingsherinneringen) en akkoord met de servicevoorwaarden. Daarna:

  1. Plaatst het een HTTP-01 challenge-bestand in je web root
  2. Vraagt Let's Encrypt om het te verifieren
  3. Downloadt het ondertekende certificaat
  4. Past je Nginx server block aan met TLS-richtlijnen
  5. Herlaadt Nginx

Verifieer dat het certificaat is uitgegeven:

sudo ls -la /etc/letsencrypt/live/example.com/

Je zou het volgende moeten zien:

lrwxrwxrwx 1 root root  ... cert.pem -> ../../archive/example.com/cert1.pem
lrwxrwxrwx 1 root root  ... chain.pem -> ../../archive/example.com/chain1.pem
lrwxrwxrwx 1 root root  ... fullchain.pem -> ../../archive/example.com/fullchain1.pem
lrwxrwxrwx 1 root root  ... privkey.pem -> ../../archive/example.com/privkey1.pem

Dit zijn symlinks. fullchain.pem is je certificaat plus de intermediate CA-keten. privkey.pem is je private key (prive-sleutel).

Controleer of Nginx draait met de nieuwe configuratie:

sudo nginx -t && sudo systemctl status nginx

nginx -t test de configuratiesyntax. Als het test is successful toont, is de configuratie geldig.

Wat wijzigt Certbot in je Nginx-configuratie?

Certbot voegt meerdere regels toe aan je server block. Dit is wat het invoegt (de regels gemarkeerd met # managed by Certbot):

server {
    server_name example.com www.example.com;

    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    # ... je bestaande location blocks ...
}

Het bestand options-ssl-nginx.conf bevat de standaard TLS-instellingen van Certbot. We vervangen deze door sterkere instellingen in het hardeninggedeelte hieronder.

Certbot maakt ook een tweede server block aan om HTTP naar HTTPS te redirecten. We verbeteren die redirect in het volgende gedeelte.

Je kunt precies zien wat er is gewijzigd door je configuratie te vergelijken:

sudo diff /etc/nginx/conf.d/example.com.conf /etc/nginx/conf.d/example.com.conf.bak 2>/dev/null || echo "No backup found. Certbot modifies in place."

Hoe redirect je HTTP naar HTTPS in Nginx?

Al het HTTP-verkeer moet worden geredirect naar HTTPS met een 301 (permanent) redirect. Certbot voegt dit mogelijk automatisch toe, maar de standaardmethode gebruikt een if-statement binnen het bestaande server block. Dat is een anti-pattern in Nginx. Een apart server block is netter en betrouwbaarder.

Vervang de redirect van Certbot door een apart server block. Bewerk je configuratiebestand (het pad hangt af van je setup; meestal /etc/nginx/conf.d/example.com.conf):

# HTTP -> HTTPS redirect (separate server block, not an if-statement)
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Dit gaat in hetzelfde bestand als je HTTPS server block, of in een apart bestand. Zorg ervoor dat je elk door Certbot gegenereerd redirect-block verwijdert om duplicaten te voorkomen.

Test en herlaad:

sudo nginx -t
sudo systemctl reload nginx

Verifieer de redirect vanaf je lokale machine:

curl -I http://example.com

Verwachte output:

HTTP/1.1 301 Moved Permanently
Location: https://example.com/

Hoe harden je TLS-instellingen voor een productieserver?

De standaard TLS-configuratie van Certbot (options-ssl-nginx.conf) is bewust conservatief. Voor een productieserver wil je strakkere instellingen. We volgen Mozilla's Intermediate-profiel van de SSL Configuration Generator, die een balans biedt tussen beveiliging en clientcompatibiliteit tot Firefox 27, Chrome 31 en Android 4.4.2.

Maak een snippet-bestand dat je kunt includen vanuit elk server block:

sudo nano /etc/nginx/snippets/tls-params.conf

Voeg het volgende toe:

# TLS protocol versions — TLS 1.2 and 1.3 only
# TLS 1.0 and 1.1 are deprecated (RFC 8996)
ssl_protocols TLSv1.2 TLSv1.3;

# Ciphers — Mozilla Intermediate profile (January 2026)
# Source: https://ssl-config.mozilla.org/
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;

# DH parameters — 2048-bit, RFC 7919 ffdhe2048
ssl_dhparam /etc/nginx/dhparam.pem;

# Session settings
ssl_session_timeout 1d;
ssl_session_cache shared:TLS:10m;
ssl_session_tickets off;

# HSTS — tell browsers to always use HTTPS (2 years)
# Only add includeSubDomains if ALL subdomains use HTTPS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

# Hide Nginx version in error pages and headers
server_tokens off;

Genereer het DH-parametersbestand (dit duurt een paar seconden):

sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048

Verifieer dat het bestand is aangemaakt:

sudo ls -la /etc/nginx/dhparam.pem

Werk nu je HTTPS server block bij om deze instellingen te gebruiken in plaats van de standaardinstellingen van Certbot. Verwijder de regel include /etc/letsencrypt/options-ssl-nginx.conf; en de regel ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;. Vervang ze door:

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;

    # TLS hardening (replaces Certbot defaults)
    include snippets/tls-params.conf;

    # ... your location blocks ...
}

Test en herlaad:

sudo nginx -t
sudo systemctl reload nginx

Welke TLS-versies en ciphers moet je gebruiken?

Mozilla publiceert drie TLS-profielen. Hier is de vergelijking:

Profiel Protocollen Oudste compatibele client Toepassing
Modern Alleen TLS 1.3 Firefox 63, Chrome 70, Android 10 Diensten waar alle clients recent zijn
Intermediate TLS 1.2 + 1.3 Firefox 27, Chrome 31, Android 4.4 Algemene webservers
Old TLS 1.0 + 1.1 + 1.2 + 1.3 Firefox 1, Chrome 1, IE 8 Alleen legacy-systemen

Gebruik Intermediate tenzij je een specifieke reden hebt om dat niet te doen. Het dekt 99,9%+ van de huidige browsers en sluit zwakke protocollen uit. TLS 1.0 en 1.1 zijn formeel verouderd verklaard door RFC 8996 in maart 2021.

De cipher-lijst in ons snippet gebruikt alleen AEAD-ciphers (GCM en ChaCha20-Poly1305). ssl_prefer_server_ciphers off laat de client zijn voorkeurs-cipher kiezen. Dit is de aanbeveling van Mozilla, omdat moderne clients betere keuzes maken dan een statische servervoorkeur.

Ondersteunt Let's Encrypt nog OCSP stapling?

Nee. Let's Encrypt heeft zijn OCSP-dienst stopgezet op 6 augustus 2025. Certificaten die na mei 2025 zijn uitgegeven, bevatten geen OCSP-responder-URL. Intrekkingsstatus wordt nu uitsluitend gepubliceerd via Certificate Revocation Lists (CRL's). Als je alleen Let's Encrypt-certificaten gebruikt, verwijder dan alle ssl_stapling-richtlijnen uit je Nginx-configuratie.

Dit is de tijdlijn:

  1. December 2024. Let's Encrypt kondigde het plan aan om OCSP te beeindigen.
  2. 30 januari 2025. Certificaten die de OCSP Must-Staple-extensie aanvroegen, begonnen te falen.
  3. 7 mei 2025. Nieuwe certificaten bevatten geen OCSP-responder-URL's meer. CRL-URL's werden toegevoegd.
  4. 6 augustus 2025. De OCSP-dienst werd volledig stopgezet. Alle eerder uitgegeven certificaten met OCSP-URL's zijn inmiddels verlopen.

Als je ssl_stapling on; of ssl_stapling_verify on; tegenkomt in een handleiding of configuratiefragment, is dat verouderd advies voor Let's Encrypt-gebruikers. Deze richtlijnen zijn onschadelijk (Nginx negeert ze stilletjes wanneer er geen OCSP-responder-URL is), maar ze voegen onnodige rommel toe. Verwijder ze.

Als je certificaten van een andere CA gebruikt die nog wel OCSP aanbiedt, blijven deze richtlijnen geldig voor die certificaten.

Waarom heeft Let's Encrypt OCSP laten vallen? Twee redenen. OCSP is een privacyrisico: elke keer dat een browser de intrekkingsstatus van een certificaat controleerde via OCSP, kwam de CA te weten welke site werd bezocht vanaf welk IP-adres. Op het hoogtepunt verwerkte de OCSP-dienst van Let's Encrypt 340 miljard verzoeken per maand. De overstap naar CRL's elimineert dat privacylek. CRL's worden in bulk door browsers gedownload, dus er gaat geen per-bezoek verzoek naar de CA.

Hoe schakel je HTTP/2 in met Nginx?

HTTP/2 multiplext verzoeken over een enkele verbinding, waardoor de latency afneemt. Als je Nginx hebt geinstalleerd vanuit de officiele nginx.org-repository (versie 1.25.1 of later), schakel je HTTP/2 in met de http2-richtlijn in je server block.

Voeg http2 on; toe in je HTTPS server block:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    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 snippets/tls-params.conf;

    # ... your location blocks ...
}

De http2 on;-richtlijn verving de verouderde listen 443 ssl http2;-syntax in Nginx 1.25.1. De oude syntax werkt nog maar geeft deprecation-waarschuwingen in het error log. Als je de door de distributie meegeleverde Nginx gebruikt (1.22 op Debian 12, 1.24 op Ubuntu 24.04), gebruik dan de oude listen 443 ssl http2;-syntax.

Test en herlaad:

sudo nginx -t
sudo systemctl reload nginx

Verifieer dat HTTP/2 actief is:

curl -I --http2 -s https://example.com | head -1

Verwachte output:

HTTP/2 200

Als je in plaats daarvan HTTP/1.1 ziet, controleer dan of http2 on; in het juiste server block staat en of je Nginx-versie het ondersteunt.

Hoe werkt automatische certificaatverlenging?

Let's Encrypt-certificaten verlopen na 90 dagen. Certbot installeert een systemd-timer (certbot.timer) die twee keer per dag controleert of een certificaat binnen 30 dagen verloopt. Zo ja, dan wordt het automatisch verlengd. Je hoeft geen cronjob in te stellen.

Controleer of de timer actief is:

systemctl status certbot.timer

Je zou Active: active (waiting) moeten zien en een regel met het volgende triggertijdstip.

Controleer wanneer de volgende verlenging plaatsvindt:

systemctl list-timers certbot.timer

Dit toont de NEXT- en LAST-uitvoertijden.

Verlenging testen zonder daadwerkelijk te verlengen

Voer een dry-run uit om te verifieren dat het verlengingsproces end-to-end werkt:

sudo certbot renew --dry-run

Dit neemt contact op met de Let's Encrypt staging-server en simuleert een volledige verlenging. Als het Congratulations, all simulated renewals succeeded toont, is je setup correct.

Een deploy hook instellen om Nginx te herladen

Wanneer Certbot een certificaat verlengt, moet Nginx herladen worden om de nieuwe bestanden op te pikken. Configureer een deploy hook die alleen bij succesvolle verlenging wordt uitgevoerd:

sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Voeg toe:

#!/bin/bash
/usr/bin/systemctl reload nginx

Maak het uitvoerbaar:

sudo chmod 700 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Verifieer de rechten:

ls -la /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Verwachte output toont -rwx------ (alleen root kan lezen en uitvoeren).

De deploy hook-directory voert scripts alleen uit na een succesvolle verlenging, niet bij elke timer-tick. Dit voorkomt onnodige herladingen.

Hoe verifieer je dat je TLS-setup correct is?

Na het afronden van alle bovenstaande stappen, voer je deze verificatiecommando's uit. Elk commando controleert een ander aspect van je setup.

De certificaatketen controleren met OpenSSL

Vanaf je lokale machine:

openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer

Verwachte output:

notBefore=Mar 19 00:00:00 2026 GMT
notAfter=Jun 17 00:00:00 2026 GMT
subject=CN = example.com
issuer=C = US, O = Let's Encrypt, CN = R12

Let op: de notAfter-datum moet ongeveer 90 dagen na uitgifte zijn. De issuer moet Let's Encrypt zijn. De huidige RSA-intermediates zijn R12 en R13. Voor ECDSA-certificaten zoek je naar E7 of E8.

De TLS-versie en cipher in gebruik controleren

openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null | grep -E "Protocol|Cipher"

Verwacht:

    Protocol  : TLSv1.3
    Cipher    : TLS_AES_256_GCM_SHA384

Als je TLSv1.2 ziet, is dat ook prima. Het hangt af van welke versie je lokale OpenSSL prefereert.

HTTPS-headers controleren

curl -I https://example.com

Zoek naar:

HTTP/2 200
strict-transport-security: max-age=63072000; includeSubDomains

Als strict-transport-security ontbreekt, controleer dan de add_header-regel in je TLS-snippet. De parameter always zorgt ervoor dat de header ook bij foutresponses wordt meegestuurd.

Overzicht verificatiecommando's

Commando Wat het controleert Waar je op let
dig +short example.com DNS-resolutie Het IP van je server
curl -I http://example.com HTTP-redirect 301 met Location: https://
curl -I https://example.com HTTPS + headers HTTP/2 200, HSTS-header
openssl s_client -connect ... Certificaatketen, TLS-versie Let's Encrypt issuer, TLSv1.2 of 1.3
certbot renew --dry-run Verlengingsproces all simulated renewals succeeded
systemctl status certbot.timer Auto-verlengingstimer active (waiting)

Testen met SSL Labs

Voor een grondige externe audit kun je je domein indienen bij SSL Labs Server Test. Met de configuratie uit deze handleiding zou je een A of A+ score moeten behalen. De A+ vereist HSTS, die we in het TLS-snippet hebben ingeschakeld.

Volledige Nginx-configuratiereferentie

Hier is het volledige server block met alle instellingen uit deze tutorial gecombineerd:

# HTTP -> HTTPS redirect
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# HTTPS server block
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name example.com www.example.com;

    # Let's Encrypt certificate
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # TLS hardening
    include snippets/tls-params.conf;

    root /var/www/example.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    # Deny access to hidden files
    location ~ /\. {
        deny all;
    }
}

En het TLS-snippet op /etc/nginx/snippets/tls-params.conf:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_dhparam /etc/nginx/dhparam.pem;

ssl_session_timeout 1d;
ssl_session_cache shared:TLS:10m;
ssl_session_tickets off;

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
server_tokens off;

Voor aanvullende beveiligingsheaders zoals Content-Security-Policy, X-Frame-Options en Permissions-Policy, zie Nginx-beveiligingshardening.

Gaat er iets mis?

Certbot meldt "Could not automatically find a matching server block" Certbot zoekt naar een server_name-richtlijn die overeenkomt met je -d-domein. Zorg ervoor dat je server block-bestand in /etc/nginx/conf.d/ of /etc/nginx/sites-enabled/ staat en server_name example.com; bevat.

Certbot meldt "Connection refused" of "Challenge failed" Poort 80 moet open zijn. Controleer je firewall:

sudo ufw status          # if using UFW
sudo nft list ruleset    # if using nftables

Verifieer ook dat Nginx luistert op poort 80:

sudo ss -tlnp | grep ':80'

"SSL: error" in het Nginx error log na het bewerken van TLS-instellingen Je hebt waarschijnlijk een syntaxfout in de cipher-string of een ontbrekend bestandspad. Controleer:

sudo nginx -t
sudo journalctl -u nginx -n 20 --no-pager

Browser toont "NET::ERR_CERT_DATE_INVALID" Het certificaat is mogelijk verlopen. Controleer de verloopdatum:

sudo certbot certificates

Als het verlopen is, forceer een verlenging:

sudo certbot renew --force-renewal

certbot renew --dry-run mislukt Veelvoorkomende oorzaak: de DNS van het domein wijst niet meer naar deze server, of poort 80 is geblokkeerd. Certbot heeft HTTP-01-toegang nodig voor verlenging.

HTTP/2 werkt niet Controleer je Nginx-versie: nginx -v. Als deze lager is dan 1.25.1, gebruik dan listen 443 ssl http2; in plaats van de aparte http2 on;-richtlijn. Als het 1.25.1+ is, zorg er dan voor dat http2 on; in het juiste server-block staat (niet in http of location).


Copyright 2026 Virtua.Cloud. Alle rechten voorbehouden. Deze inhoud is een origineel werk van het Virtua.Cloud-team. Reproductie, herpublicatie of herdistributie zonder schriftelijke toestemming is verboden.

Klaar om het zelf te proberen?

Deploy uw eigen server in seconden. Linux, Windows of FreeBSD.

Bekijk VPS-aanbod