Table of Contents – Nginx HTTP3 Quic Setup
- Overview
- Prerequisites
- Quick Architecture
- Install / Setup
- Base Configuration
- Reload/Enable & Health Checks
- Security / Hardening
- Performance & Optimization
- Backup & Restore
- Troubleshooting (Top issues)
- Key Takeaways & Next Steps
Overview
Nginx HTTP/3 QUIC setup delivers faster, more reliable TLS connections. This guide shows a clean, repeatable configuration you can use in production.
HTTP/3 over QUIC reduces handshake latency and improves mobile performance on lossy networks. Nginx can serve HTTP/3 and HTTP/2 simultaneously on 443 and advertise support via Alt-Svc. This guide provides distro-specific install steps and a unified configuration you can copy-paste.
Further reading: Nginx Docs, RFC 9114 (HTTP/3). These resources complement this nginx http3 quic setup tutorial.
Prerequisites
- Distros covered: Ubuntu/Debian, RHEL/Rocky/CentOS Stream, Fedora, Arch/Manjaro, openSUSE/SLE.
- Requirements: public DNS (DOMAIN), TCP/UDP 443 open, sudo access.
- Hardware: ≥1 vCPU, ≥1GB RAM.
- Placeholders to replace: DOMAIN, WEBROOT (e.g., /var/www/html), EMAIL.
Quick Architecture
Client (HTTP/3-capable)
|
v
Internet — TLS:443 (TCP+UDP)
|
v
Nginx (HTTP/3 + HTTP/2)
|
v
Static files / Upstream app
Install / Setup
1) Install a recent Nginx build (verify HTTP/3 support) — steps below are tailored for your nginx http3 quic setup on major Linux distros.
Ubuntu/Debian — recommended for a quick nginx http3 quic setup.
sudo apt update && sudo apt install -y curl gnupg2 ca-certificates lsb-release
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /usr/share/keyrings/nginx.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx.gpg] http://nginx.org/packages/$(. /etc/os-release && echo $ID) $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update && sudo apt install -y nginx
nginx -V 2>&1 | tr ' ' '\n' | grep -iE 'quic|http3' || echo "Proceed; if missing, consider vendor repo/newer build"
RHEL / Rocky / CentOS Stream — works great for production-grade nginx http3 quic setup.
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --set-enabled crb || true
sudo dnf -y install nginx
nginx -V 2>&1 | tr ' ' '\n' | grep -iE 'quic|http3' || echo "If QUIC is missing, use official nginx repo or a newer build"
Fedora — simple path for your nginx http3 quic setup.
sudo dnf -y install nginx
nginx -V 2>&1 | tr ' ' '\n' | grep -iE 'quic|http3' || echo "If QUIC is missing, consider nginx mainline/official repo"
Arch / Manjaro — ensure your build includes QUIC for this nginx http3 quic setup.
sudo pacman -Sy --noconfirm nginx certbot
# If nginx package lacks HTTP/3, consider AUR or official nginx repo builds.
nginx -V 2>&1 | tr ' ' '\n' | grep -iE 'quic|http3' || echo "If QUIC is missing, use an alternate build with QUIC"
openSUSE / SLE — verify QUIC-enabled packages for your nginx http3 quic setup.
sudo zypper refresh
sudo zypper install -y nginx certbot python3-certbot-nginx
nginx -V 2>&1 | tr ' ' '\n' | grep -iE 'quic|http3' || echo "If QUIC is missing, use newer repo or build with QUIC support"
2) Obtain Let’s Encrypt certificates (try Nginx plugin; if not available, use webroot).
# Try nginx plugin first
sudo certbot --nginx -d DOMAIN -d www.DOMAIN --redirect -m EMAIL --agree-tos --non-interactive || sudo certbot certonly --webroot -w WEBROOT -d DOMAIN -d www.DOMAIN -m EMAIL --agree-tos --non-interactive
sudo systemctl enable --now certbot.timer 2>/dev/null || true
sudo systemctl enable --now certbot-renew.timer 2>/dev/null || true
Base Configuration
Create a complete vhost with HTTP/3/HTTP/2, static caching, and minimal security headers. This base block is the heart of your nginx http3 quic setup.
# /etc/nginx/conf.d/DOMAIN.conf
sudo tee /etc/nginx/conf.d/DOMAIN.conf > /dev/null <<'NGINX'
server {
listen 443 ssl http2;
listen 443 quic reuseport;
server_name DOMAIN www.DOMAIN;
root WEBROOT;
index index.html index.htm;
ssl_certificate /etc/letsencrypt/live/DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/DOMAIN/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
add_header Alt-Svc 'h3=":443"; ma=86400' always;
# Compression
gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
# Static caching
location /assets/ {
expires 7d;
add_header Cache-Control "public, max-age=604800, immutable";
}
# Security headers
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
location / {
try_files $uri $uri/ =404;
}
}
# HTTP -> HTTPS
server {
listen 80;
server_name DOMAIN www.DOMAIN;
return 301 https://$host$request_uri;
}
NGINX
Reload/Enable & Health Checks
sudo nginx -t && sudo systemctl reload nginx
curl -I https://DOMAIN | sed -n '1,20p'
openssl s_client -connect DOMAIN:443 -tls1_3 -brief </dev/null | sed -n '1,12p'
Security / Hardening
sudo ufw allow 80/tcp 2>/dev/null || true
sudo ufw allow 443/tcp 2>/dev/null || true
sudo ufw allow 443/udp 2>/dev/null || true
sudo ufw enable 2>/dev/null || true
sudo tee /etc/fail2ban/jail.d/nginx.conf > /dev/null <<'JAIL'
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/*access.log
maxretry = 6
JAIL
sudo systemctl restart fail2ban 2>/dev/null || true
Performance & Optimization
- Keep TLS 1.3 enabled; add OCSP stapling if you manage chain certs.
- Use immutable caching and versioned filenames for static assets.
- Prefer Brotli when available; otherwise gzip is fine.
sudo tee /etc/nginx/conf.d/DOMAIN-tuning.conf > /dev/null <<'TUNE'
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:20m inactive=24h use_temp_path=off;
map $sent_http_content_type $static_bypass {
default 0;
"~*text/" 0;
"~*application/javascript" 0;
"~*image/svg\+xml" 0;
}
TUNE
sudo nginx -t && sudo systemctl reload nginx
Backup & Restore
sudo tar czf nginx-DOMAIN-backup-$(date +%F).tgz /etc/nginx/conf.d/DOMAIN.conf /etc/letsencrypt/live/DOMAIN /etc/letsencrypt/archive/DOMAIN
# Restore:
# sudo tar xzf nginx-DOMAIN-backup-YYYY-MM-DD.tgz -C /
Troubleshooting (Top issues)
1) HTTP/3 not negotiated — Alt-Svc missing or package lacks QUIC support.
grep -R "Alt-Svc" -n /etc/nginx/conf.d && sudo nginx -t
2) UDP/443 blocked — firewall/provider filtering.
sudo ss -lunpt | grep 443 || echo 'Open UDP/443 on server and upstream firewall'
3) Certbot fails — DNS not propagated or port 80 blocked.
dig +short DOMAIN && curl -I http://DOMAIN | head -n1
4) Old Nginx — install a newer vendor/official build with QUIC.
Key Takeaways & Next Steps
- HTTP/3 improves TTFB and resilience on flaky networks.
- Verify QUIC support with nginx -V; switch repos if needed.
- Next: add WAF rules, rate limiting, and a CDN for global reach.
