Menu
Hosting Domeny VPS SSL Kalkulator Porównania FAQ
Aktywne kody
Wszystkie kody rabatowe

HTTP/3 i QUIC - konfiguracja na Nginx i Caddy

Opublikowano: 10 kwietnia 2026 · Kategoria: Hosting / Wydajność

HTTP/3 to trzecia główna wersja protokołu HTTP, oparta na QUIC (Quick UDP Internet Connections) zamiast TCP. Eliminuje klasyczny problem "head-of-line blocking", przyspiesza ładowanie stron na wolnych połączeniach i wspiera migrację połączeń bez zrywania sesji. Oto jak go uruchomić.

Ewolucja HTTP: 1.1 → 2 → 3

Cecha HTTP/1.1 HTTP/2 HTTP/3
Transport TCP TCP UDP (QUIC)
Multiplexing Brak (pipelining) Tak (strumienie) Tak (niezależne strumienie)
Head-of-line blocking Tak (poziom połączenia) Tak (poziom TCP) Nie
TLS Opcjonalne (TLS 1.2/1.3) Wymagane (TLS 1.2+) Wbudowane TLS 1.3
Handshake RTT 1-3 RTT 1-2 RTT 0-1 RTT (0-RTT resumption)
Connection migration Nie Nie Tak (zmiana IP bez przerwy)

Kluczowa różnica: QUIC działa na UDP, więc każdy strumień HTTP/3 jest niezależny. Utrata pakietu w jednym strumieniu (np. obraz) nie wstrzymuje pobierania innych zasobów (CSS, JS) - tak jak to dzieje się w HTTP/2 na TCP.

Opcja 1: Caddy - HTTP/3 bez konfiguracji

Caddy to najprostszy sposób na HTTP/3. Od wersji 2.6 QUIC jest domyślnie włączony - wystarczy skonfigurować domenę z HTTPS:

# Instalacja Caddy (Ubuntu/Debian)
apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install caddy
# /etc/caddy/Caddyfile
example.com {
    root * /var/www/html
    file_server

    # HTTP/3 jest włączone automatycznie - nic nie musisz konfigurować!
    # Caddy dodaje nagłówek Alt-Svc: h3=":443"; ma="2592000"

    # Opcjonalnie: wymuś HTTP/3 przez nagłówek
    header Alt-Svc `h3=":443"; ma=86400`
}
systemctl reload caddy

# Weryfikacja
curl -sI https://example.com | grep -i alt-svc
# Oczekiwane: Alt-Svc: h3=":443"; ma=2592000

Ważne: QUIC używa UDP port 443. Upewnij się, że firewall przepuszcza UDP 443 (nie tylko TCP): ufw allow 443/udp.

Caddy HTTP/3 - kiedy jednak trzeba coś ustawić

W Caddy 2.6 i nowszych HTTP/3 jest domyślne, więc w większości przypadków jedyną przyczyną braku "h3" jest zablokowany UDP. Jawna konfiguracja protokołów przydaje się, gdy chcesz HTTP/3 świadomie wyłączyć (np. do testów porównawczych) albo gdy dziedziczysz Caddyfile, w którym ktoś ograniczył listę protokołów. Służy do tego blok servers w opcjach globalnych:

# /etc/caddy/Caddyfile - opcje globalne na samej górze pliku
{
    servers {
        protocols h1 h2 h3   # domyślny zestaw; usuń h3, aby wyłączyć HTTP/3
    }
}

example.com {
    reverse_proxy 127.0.0.1:3000
}

Dwie pułapki spotykane najczęściej:

  • Caddy w Dockerze - samo "443:443" w sekcji ports publikuje tylko TCP. Dla HTTP/3 potrzebne jest dodatkowe mapowanie "443:443/udp", inaczej kontener nasłuchuje na UDP, ale ruch z zewnątrz do niego nie dociera.
  • Ostrzeżenie o buforach UDP - Caddy (biblioteka quic-go) może logować komunikat "failed to sufficiently increase receive buffer size". HTTP/3 działa dalej, ale przy większym ruchu warto podnieść limity jądra: sysctl -w net.core.rmem_max=7500000 oraz sysctl -w net.core.wmem_max=7500000 (na stałe w /etc/sysctl.d/).

Opcja 2: Nginx z QUIC (mainline >= 1.25.0)

Od Nginx 1.25.0 (mainline) wbudowana jest obsługa HTTP/3 i QUIC bez patchowania. Wymaga OpenSSL 3.x lub BoringSSL:

# Instalacja Nginx mainline (Ubuntu)
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" | tee /etc/apt/sources.list.d/nginx.list

apt update && apt install nginx

# Sprawdzenie wersji i obsługi HTTP/3
nginx -V 2>&1 | grep -o 'with-http_v3_module'
# /etc/nginx/sites-available/http3-example.conf

server {
    listen 443 ssl;
    listen 443 quic reuseport;  # HTTP/3 na UDP
    listen [::]:443 ssl;
    listen [::]:443 quic reuseport;

    server_name example.com;

    http2 on;  # HTTP/2 dla klientów TCP (Nginx 1.25.1+)
    http3 on;  # domyślnie włączone, wpisane dla czytelności

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;  # QUIC i tak negocjuje TLS 1.3

    # Informuj przeglądarkę o HTTP/3
    add_header Alt-Svc 'h3=":443"; ma=86400' always;
    add_header X-Protocol $http3 always;  # "h3" jeśli żądanie przyszło po HTTP/3

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

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

# Przekierowanie HTTP → HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}
nginx -t && systemctl reload nginx

# Sprawdzenie logów HTTP/3 - dodaj $http3 do log_format
# log_format main '$remote_addr [$time_local] "$request" $status $http3';
# access_log /var/log/nginx/access.log main;

Nginx QUIC i HTTP/3 - dyrektywy, wiele vhostów i 0-RTT

Obsługę QUIC i HTTP/3 zapewnia moduł ngx_http_v3_module, dostępny od Nginx 1.25.0 (nadal oznaczany w dokumentacji jako eksperymentalny). Moduł musi być wkompilowany - jeśli nginx -V nie pokazuje --with-http_v3_module, parametr quic w dyrektywie listen zakończy się błędem przy nginx -t. Pakiety mainline z repozytorium nginx.org mają ten moduł, starsze pakiety z repozytoriów dystrybucji często nie.

reuseport tylko raz na port

Najczęstszy błąd przy kilku stronach na jednym serwerze to skopiowanie listen 443 quic reuseport; do każdego vhosta. Parametr reuseport (podobnie jak default_server) może wystąpić tylko raz dla danej pary adres:port, w przeciwnym razie Nginx zgłosi duplikat opcji listen. W pozostałych blokach server wystarczy samo quic:

# Pierwszy vhost (np. domyślny)
server {
    listen 443 ssl;
    listen 443 quic reuseport;
    server_name example.com;
    # ...
}

# Każdy kolejny vhost na tym samym IP i porcie
server {
    listen 443 ssl;
    listen 443 quic;   # bez reuseport
    server_name sklep.example.com;
    add_header Alt-Svc 'h3=":443"; ma=86400' always;
    # ...
}

Alt-Svc w Nginx: dziedziczenie add_header

Przeglądarka przechodzi na HTTP/3 dopiero wtedy, gdy zobaczy nagłówek Alt-Svc: h3=":443"; ma=86400 (ma to czas w sekundach, 86400 = doba). W Nginx łatwo go zgubić: jeśli w bloku location pojawi się jakakolwiek własna dyrektywa add_header (np. Cache-Control dla statyków), nagłówki z poziomu server nie są dziedziczone i Alt-Svc znika z odpowiedzi. Rozwiązanie to powtórzenie Alt-Svc w takim location albo trzymanie wspólnych nagłówków w pliku dołączanym przez include. Bez parametru always nagłówek nie jest dodawany do odpowiedzi z błędem (np. 404, 500).

0-RTT (ssl_early_data) i dodatkowe dyrektywy QUIC

Dyrektywa ssl_early_data on; włącza 0-RTT: powracający klient wysyła żądanie już w pierwszym pakiecie. Dane wysłane w 0-RTT mogą zostać powtórzone przez atakującego (replay attack), dlatego dokumentacja Nginx zaleca przekazanie zmiennej $ssl_early_data do aplikacji, która może wtedy odrzucić nieidempotentne żądania (np. POST składający zamówienie) kodem 425 Too Early. Jeśli aplikacja tego nie obsługuje, bezpieczniej zostawić 0-RTT wyłączone. Przy buildzie z OpenSSL (warstwa zgodności QUIC) 0-RTT w QUIC i tak nie jest dostępne - wymaga bibliotek takich jak BoringSSL, LibreSSL lub QuicTLS.

ssl_early_data on;
proxy_set_header Early-Data $ssl_early_data;  # "1" gdy żądanie przyszło w 0-RTT

quic_retry on;  # walidacja adresu klienta (utrudnia spoofing IP)
quic_gso on;    # wysyłanie pakietów z segmentation offload (Linux)

Apache a HTTP/3 i QUIC - realne opcje

Apache httpd (gałąź 2.4) nie ma natywnej obsługi HTTP/3 ani QUIC - nie istnieje moduł analogiczny do mod_http2, który dałoby się po prostu włączyć. Jeśli strona stoi na Apache, a chcesz serwować ją po HTTP/3, masz trzy praktyczne drogi:

  • Reverse proxy przed Apache - Caddy albo Nginx przyjmuje ruch na 443 (TCP i UDP), obsługuje TLS i HTTP/3, a do Apache przekazuje żądania lokalnie po HTTP/1.1. Apache przenosisz na port wewnętrzny, np. 127.0.0.1:8080. Konfiguracja .htaccess dalej działa, bo żądania nadal obsługuje Apache.
  • CDN z HTTP/3 - np. Cloudflare z włączoną opcją HTTP/3 (with QUIC). Przeglądarka łączy się z CDN po HTTP/3, a CDN z Twoim serwerem po HTTP/1.1 lub HTTP/2, więc na serwerze z Apache nie trzeba niczego zmieniać ani otwierać UDP 443.
  • Zamiana Apache na LiteSpeed - LiteSpeed Web Server (Enterprise) obsługuje HTTP/3 i czyta konfigurację Apache oraz pliki .htaccess, dlatego wielu dostawców hostingu współdzielonego używa go zamiast Apache. Darmowy OpenLiteSpeed też obsługuje HTTP/3, ale zgodność z .htaccess jest w nim tylko częściowa (głównie reguły rewrite).

Przykład najprostszego wariantu z Caddy przed Apache na tym samym VPS:

# 1. Apache tylko lokalnie - /etc/apache2/ports.conf
Listen 127.0.0.1:8080
# oraz w vhoście: <VirtualHost 127.0.0.1:8080>

# 2. Prawdziwe IP odwiedzających w logach Apache
a2enmod remoteip
# w konfiguracji Apache:
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1

# 3. /etc/caddy/Caddyfile - TLS, HTTP/2 i HTTP/3 po stronie Caddy
example.com {
    reverse_proxy 127.0.0.1:8080
}

Uwaga: aplikacja za proxy (np. WordPress) widzi połączenie z Caddy po zwykłym HTTP. Caddy przekazuje nagłówek X-Forwarded-Proto: https - aplikacja musi go uwzględniać, inaczej możesz dostać pętlę przekierowań na HTTPS.

Konfiguracja firewalla - UDP 443 obowiązkowe

# UFW
ufw allow 443/tcp
ufw allow 443/udp  # QUIC wymaga UDP!

# iptables (alternatywnie)
iptables -A INPUT -p udp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

Uwaga na dostawców chmury: AWS, GCP i Azure mają osobne Security Groups / Firewall rules. Musisz dodać regułę UDP 443 w panelu dostawcy, nie tylko w systemowym UFW.

Port HTTP/3 i QUIC - jak przeglądarka go znajduje

HTTP/3 nie ma osobnego "portu HTTP/3" w rodzaju 8443 - standardowo używa tego samego numeru co HTTPS, czyli 443, tylko po protokole UDP. Przeglądarka nie zgaduje jednak, że serwer mówi po QUIC. Typowa sekwencja wygląda tak:

  1. Pierwsze połączenie idzie po TCP 443 (HTTP/2 lub HTTP/1.1).
  2. Serwer odpowiada nagłówkiem Alt-Svc: h3=":443"; ma=86400 - to on wskazuje port UDP, na którym działa HTTP/3.
  3. Przeglądarka zapamiętuje tę informację na czas z ma i kolejne żądania próbuje wysyłać po QUIC. Gdy UDP nie odpowiada, wraca do TCP.

Wartość w Alt-Svc może wskazywać inny port (np. h3=":8443"), ale wtedy to ten port UDP musi być otwarty i nasłuchiwać. Krok z pierwszym połączeniem po TCP można skrócić rekordem DNS typu HTTPS (np. alpn="h3,h2"), z którego przeglądarki obsługujące ten typ rekordu dowiadują się o HTTP/3 jeszcze przed połączeniem. Sprawdzenie, czy serwer faktycznie nasłuchuje na UDP i czy ruch przechodzi przez firewall:

# Czy Nginx/Caddy nasłuchuje na UDP 443?
ss -ulnp | grep ':443'

# nftables (gdy nie używasz UFW; tabela inet filter musi istnieć)
nft add rule inet filter input udp dport 443 accept

# Stan reguł UFW
ufw status | grep 443

Pamiętaj o trzech warstwach: firewall systemowy, firewall w panelu dostawcy VPS (np. Hetzner Cloud Firewall, Security Groups w AWS) i ewentualnie mapowanie portów w Dockerze. Szczegóły reguł znajdziesz w poradniku UFW - konfiguracja firewalla na VPS.

Testowanie HTTP/3

# curl z HTTP/3 (wymaga curl 7.66+ z obsługą QUIC)
curl --http3 -I https://example.com

# Sprawdź nagłówek Alt-Svc
curl -sI https://example.com | grep Alt-Svc

# Chrome DevTools - weryfikacja
# 1. F12 → Network → przeładuj stronę
# 2. Kliknij żądanie → Headers → "protocol: h3"

# chrome://net-internals/#quic - aktywne sesje QUIC
# chrome://net-internals/#http2 - wszystkie protokoły

# Narzędzie online
# https://http3check.net/?host=example.com

HTTP/3 nie działa - typowe przyczyny

  • Brak nagłówka Alt-Svc - serwer nasłuchuje na UDP, ale przeglądarka o tym nie wie. Sprawdź curl -sI https://example.com | grep -i alt-svc dla kilku adresów (strona główna, plik statyczny, 404), bo w Nginx nagłówek bywa gubiony w poszczególnych blokach location.
  • Zablokowany UDP 443 - nagłówek Alt-Svc jest, ale w DevTools wciąż widać "h2". Najczęściej brakuje reguły w firewallu dostawcy VPS albo mapowania 443/udp w Dockerze.
  • Pierwsze żądanie po h2 to norma - bez rekordu DNS HTTPS pierwsze wczytanie strony zawsze idzie po TCP. Oceniaj protokół po przeładowaniu strony, a w DevTools włącz kolumnę Protocol (prawy klik na nagłówek tabeli w zakładce Network) i szukaj wartości "h3".
  • Sieci blokujące QUIC - część sieci firmowych, publicznych hotspotów i urządzeń pośredniczących (middleboxy, firewalle UTM) blokuje lub ogranicza UDP 443. Przeglądarka wtedy po cichu wraca do HTTP/2. To zachowanie zamierzone, nie błąd serwera - dlatego TCP 443 z HTTP/2 musi zawsze działać równolegle.
  • curl bez obsługi HTTP/3 - curl z repozytoriów wielu dystrybucji nie ma wkompilowanego HTTP/3 i odrzuci flagę --http3. Sprawdź, czy curl -V pokazuje "HTTP3" w liście Features; jeśli nie, testuj przez przeglądarkę lub http3check.net.
  • Strona za CDN - gdy domena jest proxowana przez Cloudflare, o HTTP/3 dla odwiedzających decyduje ustawienie w panelu CDN, a nie konfiguracja serwera. Więcej o tym układzie w artykule CDN w hostingu - Cloudflare.

Wskazówka: po zmianie konfiguracji przeglądarka może przez pewien czas pamiętać stare informacje Alt-Svc albo nieudaną próbę QUIC. Do testów używaj okna prywatnego lub innej przeglądarki.

Kiedy HTTP/3 najbardziej pomaga?

  • Duże liczby zasobów - strony z 50+ żądaniami JS/CSS/obrazów - brak HoL blockingu przyspiesza ich równoległe pobieranie.
  • Użytkownicy mobilni - słabe, stratne połączenia 4G/5G - QUIC lepiej radzi sobie z utraconymi pakietami.
  • Aplikacje real-time - czat, streaming - 0-RTT resumption skraca czas nawiązywania sesji po przerwie.
  • Globalna publiczność - użytkownicy daleko od serwera - mniej RTT handshake.
  • Słabsza sieć - np. publiczne WiFi - QUIC jest bardziej odporny na packet loss niż TCP.

Kiedy zysk jest mały: serwer lokalny, stabilna sieć, mała liczba zasobów na stronie, już skonfigurowane HTTP/2 Push lub preload. W tych przypadkach HTTP/3 daje <5% poprawy.

LiteSpeed - HTTP/3 gotowe na hostingu

Jeśli używasz hostingu współdzielonego z LiteSpeed (np. LH.pl, CyberFolks), HTTP/3 i QUIC mogą być już aktywne po stronie serwera - bez żadnej konfiguracji z Twojej strony. Sprawdź nagłówki odpowiedzi:

curl -sI https://twojastrona.pl | grep -i 'alt-svc\|server\|x-powered'
# LiteSpeed Enterprise: server: LiteSpeed, alt-svc: h3=":443"

Najczęstsze pytania

Czym HTTP/3 różni się od HTTP/2? +
HTTP/2 działa na TCP i cierpi na "head-of-line blocking" - jeden utracony pakiet blokuje cały strumień. HTTP/3 używa QUIC (UDP), gdzie każdy strumień jest niezależny: utrata pakietu w jednym strumieniu nie blokuje pozostałych. Dodatkowo QUIC wbudowuje TLS 1.3 i obsługuje "connection migration" - połączenie nie zrywa się przy zmianie sieci (np. WiFi → LTE na smartfonie).
Czy HTTP/3 naprawdę przyspiesza strony? +
Zależy od scenariusza. Na szybkich, stabilnych łączach różnica jest minimalna (3-5%). Na słabych, stratnych połączeniach (mobilnych, satelitarnych) HTTP/3 może dać 20-30% skrócenia czasu ładowania. Największy zysk jest przy stronach z wieloma zasobami (CSS, JS, obrazy) - brak HoL blockingu przyspiesza ich równoległe pobieranie.
Jak sprawdzić czy moja strona obsługuje HTTP/3? +
Użyj curl z flagą --http3: curl --http3 -I https://twojadomena.pl. Alternatywnie otwórz DevTools Chrome → Network → kliknij żądanie i sprawdź nagłówek "protocol: h3". Możesz też użyć serwisu https://http3check.net/ lub uruchomić chrome://net-internals/#quic w Chrome aby zobaczyć aktywne sesje QUIC.
Czy Caddy obsługuje HTTP/3 automatycznie? +
Tak - od wersji 2.6 Caddy ma HTTP/3 (QUIC) włączone domyślnie (wcześniej była to opcja eksperymentalna). Wystarczy skonfigurować stronę z HTTPS (co Caddy robi automatycznie przez Let's Encrypt) i otworzyć port UDP 443 - HTTP/3 działa bez dodatkowej konfiguracji. Caddy używa biblioteki quic-go. Nie potrzebujesz patchować Nginx ani instalować BoringSSL.
Na jakim porcie działa HTTP/3 (QUIC)? +
Standardowo HTTP/3 działa na porcie 443, ale po UDP, a nie po TCP jak HTTP/1.1 i HTTP/2. Port wskazuje serwer w nagłówku Alt-Svc (np. h3=":443"), więc technicznie może to być inny port UDP. W praktyce otwierasz UDP 443 w firewallu systemowym i w firewallu dostawcy VPS, zostawiając jednocześnie TCP 443 dla klientów, którzy nie obsługują HTTP/3.
Czy Apache obsługuje HTTP/3? +
Nie - Apache httpd 2.4 nie ma natywnej obsługi HTTP/3 ani QUIC, obsługuje HTTP/1.1 i HTTP/2 (mod_http2). Żeby serwować stronę z Apache po HTTP/3, stawia się przed nim reverse proxy z obsługą QUIC (Caddy, Nginx) albo CDN (np. Cloudflare), który rozmawia z przeglądarką po HTTP/3, a z Apache po HTTP/1.1 lub HTTP/2. Alternatywą jest LiteSpeed, który obsługuje HTTP/3 i jest zgodny z konfiguracją .htaccess.
Jak włączyć HTTP/3 w Nginx? +
Potrzebujesz Nginx 1.25.0 lub nowszego z modułem ngx_http_v3_module (sprawdzisz przez nginx -V). W bloku server dodaj "listen 443 quic reuseport;" obok "listen 443 ssl;", nagłówek Alt-Svc: h3=":443"; ma=86400 i otwórz UDP 443 w firewallu. Parametr reuseport może wystąpić tylko raz dla danego adresu i portu - w kolejnych vhostach użyj samego "listen 443 quic;". Dyrektywa "http3 on;" jest domyślnie włączona, ale można ją wpisać jawnie.

Sprawdź oferty pasujące do tego scenariusza

Poniżej masz szybkie przejścia do ofert i stron z kodami rabatowymi tam, gdzie są dostępne.