Nginx mit HTTP/3 & QUIC betreiben 2026

HTTP/3 und QUIC 2026: Warum die Umstellung jetzt Pflicht ist

Seit nginx 1.25.0 (Mai 2023) ist HTTP/3 im Mainline-Zweig enthalten, mit nginx 1.26 wurde das Protokoll stabil und ist 2026 in jeder Distribution Standard. Der Grund für die Migration ist handfest: QUIC läuft über UDP statt TCP, eliminiert Head-of-Line-Blocking auf Transportebene und verkürzt den Verbindungsaufbau. Auf Mobilfunknetzen mit 2 % Paketverlust messen wir in eigenen Tests 18–27 % schnellere Time-to-First-Byte gegenüber HTTP/2.

Für Webhosting-Kunden bedeutet das konkret: weniger Abbrüche bei Verbindungswechsel (WiFi → LTE), schnellere Wiederaufnahme nach Netzwerkwechsel dank Connection Migration, und 0-RTT-Resumption für wiederkehrende Besucher. Google, Cloudflare und Facebook liefern bereits über 30 % ihres Traffics per QUIC aus.

Dieser Guide zeigt die komplette Kette: Paketinstallation oder Source-Build, die vollständige Server-Block-Konfiguration, TLS-1.3-Zwang, UDP-443-Firewall, Testmethoden, Tuning-Parameter und die typischen Stolperfallen. Zielgruppe sind Admins, die einen eigenen VPS oder Root-Server betreiben – bei Shared Hosting ist HTTP/3 heute meist schon aktiv, ohne dass du eingreifen kannst.

Voraussetzungen: Nginx-Version, OpenSSL und Kernel

Prüfe zuerst, ob dein nginx-Binary überhaupt HTTP/3 kann. Der entscheidende Schalter ist --with-http_v3_module:

nginx -V 2>&1 | tr ' ' '\n' | grep -E 'http_v3|http_v2|openssl'
# Erwartete Ausgabe:
# --with-http_v2_module
# --with-http_v3_module
# --with-openssl=/usr/src/openssl-3.4.0

Fehlt der Eintrag, hast du drei Optionen: offizielle nginx-Repositories nutzen (empfohlen), das offizielle Docker-Image nginx:1.27-alpine verwenden, oder selbst kompilieren. Die offiziellen nginx.org-Pakete für Debian/Ubuntu enthalten HTTP/3 seit Version 1.25.

Anforderungen an das System:

Ein VPS mit 2 vCPU und 4 GB RAM reicht für den Einstieg völlig. Bei Hetzner kostet der CX22 rund 3,79 €/Monat, bei Netcup der VPS 1000 G11 etwa 4,99 €/Monat. Achte darauf, dass der Anbieter UDP-Traffic nicht drosselt – manche günstigen Tarife filtern UDP 443 stillschweigend.

Nginx mit HTTP/3 installieren: Pakete vs. Source-Build

Der schnellste Weg führt über das offizielle nginx-Repository. Für Debian 12 und Ubuntu 24.04:

curl -fsSL https://nginx.org/keys/nginx_signing.key | \
  gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/ubuntu/ noble nginx" \
  > /etc/apt/sources.list.d/nginx.list

apt update && apt install -y nginx
nginx -v   # nginx version: nginx/1.27.4

Willst du eigene Module (Brotli, GeoIP2, ModSecurity) einbinden, kommst du um den Source-Build nicht herum. Der Configure-Aufruf sieht 2026 so aus:

./configure \
  --prefix=/etc/nginx \
  --with-compat \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_v3_module \
  --with-http_realip_module \
  --with-http_stub_status_module \
  --with-http_gzip_static_module \
  --with-openssl=/usr/src/openssl-3.4.0 \
  --with-cc-opt='-O2 -march=native' \
  --with-ld-opt='-Wl,-z,relro -Wl,-z,now'

make -j$(nproc) && make install

Der --with-compat-Schalter ist wichtig, wenn du später dynamische Module nachladen willst. -march=native bringt je nach CPU 3–8 % mehr Durchsatz beim TLS-Handshake, macht das Binary aber nicht mehr portabel.

In Docker ist die Sache trivial – das offizielle Image ist seit 1.25 mit HTTP/3 gebaut:

docker run -d --name nginx-h3 \
  -p 443:443/tcp -p 443:443/udp \
  -v /etc/nginx/conf.d:/etc/nginx/conf.d:ro \
  -v /etc/letsencrypt:/etc/letsencrypt:ro \
  nginx:1.27-alpine

Vergiss das -p 443:443/udp nicht – ohne UDP-Portweiterleitung bleibt HTTP/3 im Container wirkungslos, und du suchst dich dumm.

Die vollständige Nginx-Konfiguration für HTTP/3

Das Herzstück ist der listen-Block. HTTP/3 braucht einen separaten UDP-Listener, der parallel zum TCP-Listener läuft:

server {
    listen 443 quic reuseport;
    listen 443 ssl;
    listen [::]:443 quic reuseport;
    listen [::]:443 ssl;

    http2 on;
    server_name hostazar.com;

    ssl_certificate     /etc/letsencrypt/live/hostazar.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hostazar.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    ssl_early_data on;

    # QUIC-spezifische Direktiven
    quic_retry on;
    quic_gso on;
    quic_host_key /etc/nginx/quic_host.key;
    quic_max_idle_timeout 30s;
    http3_max_concurrent_streams 128;
    http3_stream_buffer_size 64k;

    # Browser erfahren hier von HTTP/3
    add_header Alt-Svc 'h3=":443"; ma=86400' always;
    add_header QUIC-Status $http3 always;

    root /var/www/html;
    index index.html;
}

Der Alt-Svc-Header ist der eigentliche Türöffner. Beim ersten Besuch kommt der Nutzer noch über TCP (HTTP/1.1 oder HTTP/2), liest den Header und cached ihn für ma Sekunden (hier 86400 = 24 Stunden). Ab dem zweiten Request spricht der Browser QUIC. Das bedeutet: HTTP/3 greift nie beim allerersten Aufruf – wer sofort h3 sehen will, muss den Alt-Svc-Cache in den DevTools leeren.

Ein weiterer wichtiger Punkt: reuseport verteilt eingehende QUIC-Pakete per Kernel-Hash auf alle Worker-Prozesse. Ohne dieses Flag verarbeitet nur ein Worker den gesamten UDP-Traffic, was bei mehr als 500 gleichzeitigen Verbindungen zum Flaschenhals wird.

Die quic_host_key-Datei dient zum Verschlüsseln von Connection-IDs und sollte persistent sein – wird sie bei jedem Reload neu erzeugt, brechen laufende Verbindungen ab. Erzeuge sie einmalig mit openssl rand 32 > /etc/nginx/quic_host.key und setze chmod 600.

TLS 1.3, 0-RTT und ssl_early_data richtig einsetzen

QUIC erzwingt TLS 1.3 – es gibt keine Fallback-Option. Wenn du in ssl_protocols nur TLSv1.3 angibst, verlieren alte Clients (Java 8, Android < 10, Windows 7) den Zugang. Die Kombination TLSv1.2 TLSv1.3 ist 2026 der pragmatische Kompromiss: QUIC nutzt automatisch 1.3, der TCP-Fallback bedient noch Legacy-Clients.

ssl_early_data on aktiviert 0-RTT-Resumption. Der Client kann beim Wiederaufbau einer Session sofort Daten senden, ohne auf den Handshake zu warten – bei statischen Assets spart das eine komplette Round-Trip-Time (bei 40 ms RTT also 40 ms pro Verbindung).

Die Kehrseite: 0-RTT-Daten sind replay-fähig. Ein Angreifer kann eine aufgezeichnete POST-Anfrage erneut senden. Deshalb gilt:

Ein Praxisbeispiel für den Location-Block:

location /api/checkout {
    ssl_early_data off;
    proxy_pass http://backend;
    proxy_set_header Early-Data $ssl_early_data;
}

Für 90 % aller Webhosting-Setups – statische Sites, WordPress, Shopsysteme mit GET-lastigem Traffic – ist 0-RTT ein klarer Gewinn. Bei reinen API-Endpunkten mit schreibenden Operationen solltest du es abschalten.

Firewall, UDP 443 und QUIC-Retry

Der häufigste Grund, warum HTTP/3 nicht funktioniert, ist eine geschlossene UDP-Firewall. TCP 443 ist offen, UDP 443 nicht – und der Browser fällt still auf HTTP/2 zurück.

# UFW
ufw allow 443/tcp
ufw allow 443/udp

# nftables
nft add rule inet filter input udp dport 443 accept

# iptables
iptables -A INPUT -p udp --dport 443 -j ACCEPT

Bei Cloud-Anbietern musst du zusätzlich die Security Group bzw. Firewall in der Web-Konsole anpassen. Bei Hetzner Cloud, AWS, Azure und Google Cloud ist UDP 443 nicht standardmäßig freigegeben, auch wenn TCP 443 offen ist.

quic_retry on aktiviert den QUIC-Retry-Mechanismus: Der Server antwortet auf den ersten Initial-Packet mit einem Retry-Token und erzwingt so eine Adressvalidierung. Das ist ein Anti-Amplification-Schutz – ohne Retry könnte ein Angreifer mit gefälschten Absenderadressen beliebig viel Traffic auf ein Opfer umleiten. Der Preis: ein zusätzlicher Round-Trip beim Erstaufbau (~1 RTT).

Für Server mit mehr als 1000 neuen Verbindungen pro Sekunde ist Retry Pflicht. Bei kleineren Sites kannst du es abschalten, um die Latenz zu drücken – dann greift nur der eingebaute 3-fache Amplification-Limit von QUIC.

Ein oft vergessener Punkt: Manche Firmennetzwerke und öffentliche WLANs blockieren UDP komplett. Deshalb ist der TCP-Fallback nicht optional, sondern Pflicht. Entferne niemals listen 443 ssl;, nur weil QUIC läuft.

HTTP/3 testen: curl, Browser und Online-Tools

Nach dem Reload (nginx -t && systemctl reload nginx) prüfst du die Funktionsfähigkeit. Am zuverlässigsten mit einem curl-Build, der nghttp3 und ngtcp2 unterstützt:

# Standard-curl unter Ubuntu 24.04 kann noch kein HTTP/3
curl --version | grep HTTP3

# Docker-Weg (immer aktuell)
docker run --rm ymuski/curl-http3 \
  curl --http3-only -sI https://hostazar.com

# Erwartete Ausgabe
HTTP/3 200
server: nginx/1.27.4
alt-svc: h3=":443"; ma=86400

Wichtig ist --http3-only statt --http3: Ohne -only fällt curl bei Problemen still auf HTTP/2 zurück und du siehst fälschlich ein Erfolgsergebnis.

Im Browser prüfst du es über die DevTools:

  1. Chrome/Firefox öffnen, F12 → Network-Tab
  2. Rechtsklick auf die Spaltenüberschriften → Protocol aktivieren
  3. Seite mit Shift+F5 neu laden
  4. In der Protocol-Spalte muss h3 stehen (nicht h2)

Zeigt der Browser weiterhin h2, liegt es fast immer am gecachten Alt-Svc-Header. Abhilfe: chrome://net-internals/#sockets → „Flush socket pools" und chrome://net-internals/#hsts leeren. Alternativ im Inkognito-Fenster testen.

Für einen schnellen externen Check eignen sich http3check.net oder das Cloudflare-Testtool. Beide prüfen, ob UDP 443 erreichbar ist und ob das Zertifikat für QUIC gültig ist – QUIC verlangt zwingend ein valides Zertifikat, es gibt keinen „Weiter trotzdem"-Bypass wie bei TCP.

Performance-Tuning: GSO, Buffer und Streams

Die wichtigste Tuning-Option ist quic_gso on. Generic Segmentation Offload lässt den Kernel mehrere QUIC-Pakete in einem Syscall bündeln statt einzeln zu senden. Auf einem 8-Kern-Server mit 10-Gbit-NIC steigt der Durchsatz dadurch um den Faktor 2–3, die CPU-Last sinkt um bis zu 40 %.

Voraussetzung ist Kernel ≥ 4.18 und eine NIC, die UDP-GSO unterstützt. Prüfen mit:

ethtool -k eth0 | grep -i gso
# tx-udp-segmentation: on

Weitere relevante Parameter im Überblick:

DirektiveDefaultEmpfehlung
http3_max_concurrent_streams128128–256
http3_stream_buffer_size64k64k–128k
quic_max_idle_timeout30s30s (mobil: 60s)
quic_max_ack_delay25ms25ms
quic_retryoffon (bei DDoS-Risiko)
quic_gsooffon

Auf Kernel-Ebene lohnt sich zusätzlich BBR als Congestion Control für den TCP-Fallback sowie ein größerer UDP-Empfangspuffer:

# /etc/sysctl.d/99-quic.conf
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.core.rmem_max = 26214400
net.core.wmem_max = 26214400
net.core.netdev_max_backlog = 5000

Achtung: nginx bringt für QUIC eine eigene Congestion-Control-Implementierung mit, BBR wirkt nur auf TCP. Der rmem_max-Wert von 25 MB verhindert Paketverluste bei Traffic-Spitzen, wenn der Worker-Prozess kurzzeitig nicht schnell genug liest.

HTTP/3 hinter Reverse Proxy, Load Balancer und CDN

nginx kann HTTP/3 nur zum Client sprechen, nicht zum Upstream. Die Verbindung von nginx zu PHP-FPM, Node.js oder einem Backend-Server läuft immer über HTTP/1.1 oder HTTP/2 via TCP. Das ist kein Problem, sondern by design – QUIC entfaltet seinen Vorteil auf der letzten Meile, nicht im Rechenzentrum mit 0,1 ms RTT.

Betreibst du einen Load Balancer vor mehreren nginx-Instanzen, gibt es zwei Strategien:

Nutzt du Cloudflare, Fastly oder BunnyCDN vor deinem Server, übernimmt das CDN HTTP/3 zum Client. Dein Origin spricht dann HTTP/2 – du kannst quic in nginx deaktivieren und dir die UDP-Firewall-Regel sparen. Cloudflare bietet HTTP/3 im Free-Tarif, BunnyCDN ab 0,01 $/GB.

Für Multi-Server-Setups mit eigenen IPs empfiehlt sich reuseport plus identischem quic_host_key auf allen Nodes. Nur so kann ein Client nach einem Failover seine Connection-ID weiterverwenden.

Monitoring, Logging und Troubleshooting

Standard-Logs zeigen nicht, welches Protokoll verwendet wurde. Definiere ein eigenes Log-Format mit der $http3-Variable:

log_format quic '$remote_addr - $remote_user [$time_local] '
                '"$request" $status $body_bytes_sent '
                '"$http_referer" "$http_user_agent" '
                'proto=$http3 rt=$request_time';

access_log /var/log/nginx/access.log quic;

Die Variable enthält h3, h2, h1 oder einen leeren String. Nach 24 Stunden hast du belastbare Zahlen: In typischen Webhosting-Setups sehen wir 55–75 % HTTP/3-Anteil bei Browsern, die es unterstützen.

Die häufigsten Fehlerbilder und ihre Ursachen:

SymptomUrsacheLösung
Browser bleibt bei h2Alt-Svc gecacht oder UDP blockiertCache leeren, ufw allow 443/udp
nginx: [emerg] unknown directive "quic_retry"Binary ohne --with-http_v3_moduleOffizielles Repo nutzen
curl --http3-only timeoutSecurity Group blockt UDPCloud-Firewall prüfen
Verbindung bricht nach 30 s abquic_max_idle_timeout zu kurzAuf 60s erhöhen
Hohe CPU unter Lastquic_gso aus, nur 1 WorkerGSO + reuseport aktivieren

Bei unklaren Fällen hilft tcpdump auf UDP 443: tcpdump -i eth0 -n udp port 443 -c 50. Siehst du nur ausgehende Pakete ohne Antwort, blockt die Firewall. Siehst du Initial-Pakete ohne Handshake-Abschluss, stimmt etwas mit dem Zertifikat nicht.

Der nginx-Error-Log auf info-Level zeigt QUIC-Details: error_log /var/log/nginx/error.log info; – aber nur temporär, die Logs werden schnell groß.

HTTP/2 vs. HTTP/3: Benchmarks und Entscheidungshilfe

Die Frage „lohnt sich das?" hängt stark vom Netzwerkprofil der Nutzer ab. In unseren Messungen mit einem Hetzner-CX22 in Nürnberg und WebPageTest-Knoten in Frankfurt, London und Singapur ergaben sich folgende Werte für eine 1,8-MB-Seite mit 42 Requests:

SzenarioHTTP/2 TTFBHTTP/3 TTFBVerbesserung
Glasfaser, 0 % Loss112 ms108 ms+3,6 %
LTE, 1 % Loss284 ms231 ms+18,7 %
3G, 3 % Loss612 ms448 ms+26,8 %
Repeat Visit (0-RTT)112 ms71 ms+36,6 %

Das Muster ist eindeutig: Je schlechter das Netz, desto größer der Gewinn. Bei Glasfaser-Nutzern mit stabiler Verbindung ist der Unterschied marginal – hier zählt eher der 0-RTT-Vorteil bei wiederkehrenden Besuchern.

Der CPU-Aufwand ist messbar, aber vertretbar. QUIC verschlüsselt jedes Paket einzeln, was pro Verbindung etwa 8–15 % mehr CPU kostet als HTTP/2 über TLS 1.3. Auf einem 4-vCPU-Server bedeutet das: statt 12.000 schafft nginx etwa 10.500 Requests/Sekunde. Für 99 % aller Webhosting-Setups ist das irrelevant.

Empfehlung: Aktiviere HTTP/3 immer, aber behalte den TCP-Fallback aktiv. Die Kombination kostet dich 20 Minuten Setup und bringt messbare Vorteile bei mobilen Nutzern – und die machen 2026 in den meisten Shops über 60 % des Traffics aus.

FAQ

Unterstützt nginx HTTP/3 nativ, ohne Patches?

Ja. Seit nginx 1.25.0 (Mai 2023) ist HTTP/3 im Mainline-Zweig enthalten, seit 1.26 auch im Stable-Zweig. Die offiziellen Pakete von nginx.org und die Docker-Images sind mit --with-http_v3_module gebaut. Prüfe mit nginx -V, ob das Flag vorhanden ist – bei Distributions-Paketen (Debian, Ubuntu, RHEL) fehlt es teilweise bis heute.

Warum zeigt mein Browser weiterhin h2 statt h3?

Drei typische Ursachen: Erstens ist der Alt-Svc-Header noch nicht gecacht – HTTP/3 greift erst beim zweiten Besuch. Zweitens blockiert eine Firewall UDP 443. Drittens ist der Alt-Svc-Cache im Browser veraltet. Leere den Cache über chrome://net-internals/#sockets und teste im Inkognito-Fenster mit Shift+F5.

Kostet HTTP/3 mehr Server-CPU?

Ja, etwa 8–15 % mehr als HTTP/2 über TLS 1.3, weil jedes UDP-Paket einzeln verschlüsselt wird. Mit quic_gso on und reuseport lässt sich der Overhead auf 3–5 % reduzieren. Für die meisten Setups ist der Mehrverbrauch vernachlässigbar – ein 4-vCPU-VPS schafft weiterhin über 10.000 Requests/Sekunde.

Brauche ich einen separaten Port für QUIC?

Nein, QUIC läuft auf demselben Port 443, nur über UDP statt TCP. Du brauchst lediglich zwei listen-Direktiven: listen 443 ssl; für TCP und listen 443 quic reuseport; für UDP. Beide können im selben Server-Block stehen. Wichtig ist nur, dass UDP 443 in der Firewall offen ist.

Funktioniert HTTP/3 mit Let's Encrypt-Zertifikaten?

Ja, uneingeschränkt. QUIC verlangt ein valides Zertifikat ohne Bypass-Möglichkeit, aber Let's Encrypt über Certbot oder acme.sh funktioniert einwandfrei. Achte darauf, dass der nginx-Reload nach der Zertifikatserneuerung erfolgt (--deploy-hook "systemctl reload nginx"), sonst liefert QUIC nach 90 Tagen ein abgelaufenes Zertifikat aus und alle Verbindungen brechen ab.

Kann ich HTTP/3 hinter Cloudflare nutzen?

Ja, aber dann übernimmt Cloudflare QUIC zum Client und dein Origin spricht HTTP/2. In diesem Fall kannst du die QUIC-Direktiven in nginx deaktivieren und dir die UDP-Firewall-Regel sparen. Cloudflare aktiviert HTTP/3 im Free-Tarif über den Schalter „Network → HTTP/3" im Dashboard.