HTTP/2 e HTTP/3 no Nginx da VPS

HTTP/1.1 abre uma conexão por recurso, browsers modernos limitam a 6 conexões simultâneas por domínio, criando fila de espera. HTTP/2 usa uma única conexão com multiplexing, eliminando essa limitação. HTTP/3 vai além: substitui TCP por QUIC (UDP), reduzindo latência em redes móveis e instáveis.

Habilitar HTTP/2 no Nginx

HTTP/2 requer HTTPS, configuração no vhost:

nginx
# /etc/nginx/sites-available/meu-site.conf

server {
    listen 443 ssl http2;          # adicionar "http2" aqui
    server_name seudominio.com.br;

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

    # TLS 1.2 e 1.3 requeridos para HTTP/2:
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305;

    # Cabeçalho para confirmar ao cliente que HTTP/2 está ativo:
    add_header X-Protocol $server_protocol;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;     # entre Nginx e app: HTTP/1.1 com keepalive
        proxy_set_header Connection "";
    }
}

# Verificar se HTTP/2 está ativo:
curl -I --http2 https://seudominio.com.br | grep -i "HTTP/"
# Deve retornar: HTTP/2 200

# Com openssl:
openssl s_client -connect seudominio.com.br:443 -alpn h2 2>/dev/null \
  | grep "ALPN protocol"
# Deve retornar: ALPN protocol: h2

Habilitar HTTP/3 (QUIC) no Nginx

HTTP/3 requer Nginx 1.25+ compilado com suporte a QUIC:

nginx
# Verificar versão do Nginx e suporte a QUIC:
nginx -V 2>&1 | grep -i quic

# Se não tiver QUIC: instalar do repositório oficial do Nginx:
sudo apt install -y gnupg2 ca-certificates lsb-release ubuntu-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
  | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
  http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" \
  | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update && sudo apt install -y nginx

# Configurar HTTP/3 no vhost:
server {
    listen 443 ssl http2;
    listen 443 quic reuseport;   # HTTP/3 via UDP porta 443

    server_name seudominio.com.br;

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

    # Informar ao browser que HTTP/3 está disponível:
    add_header Alt-Svc 'h3=":443"; ma=86400';

    ssl_early_data on;   # 0-RTT para conexões repetidas (TLS 1.3)
}

# Liberar UDP 443 no UFW (HTTP/3 usa UDP):
sudo ufw allow 443/udp

Server Push HTTP/2 (preload de recursos)

Enviar recursos ao browser antes que ele os solicite:

nginx
# Server Push: enviar CSS/JS junto com o HTML, sem esperar o browser parsear
# Funciona apenas em HTTP/2 e quando o Nginx serve o HTML diretamente

# No vhost:
location = / {
    # Push CSS e JS junto com o index.html:
    http2_push /static/app.css;
    http2_push /static/app.js;
    http2_push /static/fonts/inter.woff2;
    try_files $uri /index.html;
}

# Alternativa: header Link (mais flexível, funciona com apps):
# A aplicação Node.js envia o header e o Nginx faz o push:
location / {
    http2_push_preload on;  # processar headers Link do upstream
    proxy_pass http://127.0.0.1:3000;
}

# Na aplicação Node.js:
res.setHeader('Link', [
  '</static/app.css>; rel=preload; as=style',
  '</static/app.js>; rel=preload; as=script',
])

# Verificar push no DevTools do Chrome:
# Network → Nome → "Initiator" deve mostrar "Push / Other"

Impacto real de HTTP/2 vs HTTP/1.1

Medir o ganho de performance com ferramentas reais:

bash
# Comparar HTTP/1.1 vs HTTP/2 com curl:
time curl -o /dev/null -s -w "%{time_total}" --http1.1 https://seudominio.com.br/
time curl -o /dev/null -s -w "%{time_total}" --http2 https://seudominio.com.br/

# h2load: teste de carga específico para HTTP/2:
sudo apt install -y nghttp2-client

h2load -n 1000 -c 50 https://seudominio.com.br/api/endpoint
# -n: total de requisições
# -c: conexões simultâneas (HTTP/2 multiplexing: menos conexões = eficiente)

# Comparação direta:
h2load --h1 -n 1000 -c 50 https://seudominio.com.br/api/endpoint  # HTTP/1.1
h2load     -n 1000 -c 50 https://seudominio.com.br/api/endpoint  # HTTP/2

# Verificar no browser (Chrome DevTools):
# Network → Protocol → h2 (HTTP/2) ou h3 (HTTP/3)
# Com HTTP/2: menos conexões TCP mas mesma ou menor latência

# Medir com WebPageTest (teste real de browser):
# webpagetest.org → inserir URL → comparar HTTP/1.1 vs HTTP/2

Resolver problemas comuns do HTTP/2

Erros frequentes e como corrigir:

nginx
# Problema: HTTP/2 não está sendo negociado
# Causa: TLS não configurado ou versão SSL muito antiga
# Verificar:
curl -vI https://seudominio.com.br 2>&1 | grep -E "HTTP/|ALPN|SSL"

# Problema: ERR_HTTP2_PROTOCOL_ERROR no browser
# Causa comum: header com caractere inválido (maiúscula, espaço)
# HTTP/2 exige todos os headers em minúsculo
# No Nginx — evitar headers com maiúsculas:
# Errado:  add_header X-Custom-Header "valor"   ← OK no HTTP/1.1
# Correto: add_header x-custom-header "valor"   ← seguro no HTTP/2

# Problema: WebSocket não funciona com HTTP/2
# WebSocket não é suportado via HTTP/2 multiplexing (ainda)
# Solução: usar WebSocket via HTTP/1.1 em path separado:
location /ws {
    proxy_pass http://127.0.0.1:3001;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

# Problema: HTTP/3 não está sendo usado (Alt-Svc ignorado)
# Causa: firewall bloqueando UDP 443
sudo ufw allow 443/udp
# Verificar: curl -vI --http3 https://seudominio.com.br

Não quer configurar manualmente?

Implante o VPS em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Para APIs com muitas chamadas paralelas (dashboard que faz 10 requests simultâneos): HTTP/2 elimina o head-of-line blocking do HTTP/1.1, reduzindo latência total. Para APIs de endpoint único com payloads grandes: ganho mínimo. O maior benefício do HTTP/2 é para frontends que carregam muitos recursos (CSS, JS, imagens, fontes) em paralelo.

Depende do perfil dos usuários. HTTP/3 (QUIC) brilha em redes instáveis e móveis, reduz latência de reconexão após mudança de rede (WiFi → 4G). Para usuários com fibra estável: ganho marginal. Para apps mobile ou usuários em regiões com rede ruim: pode melhorar significativamente. Custo de implementação é baixo se você já tem Nginx 1.25+.

Não, quando Nginx termina o HTTP/2 e faz proxy para o Node.js, a comunicação entre Nginx e Node.js é HTTP/1.1 normal com keepalive. O Node.js não precisa saber nada sobre HTTP/2. Apenas a conexão entre o browser e o Nginx usa HTTP/2. Exceção: se você usar o módulo http2 nativo do Node.js diretamente (sem Nginx), precisaria adaptar o código.

Cada vez menos. Em 2023, o Chrome removeu o suporte a HTTP/2 Server Push por usar largura de banda para recursos que o browser já tem em cache. A abordagem atual preferida é o preload hint (<link rel="preload">) no HTML, o browser decide se precisa buscar o recurso. Para performance: prefira preload hints no HTML ao invés de server push.

Sim, gRPC usa HTTP/2 mandatoriamente para multiplexing de streams bidirecionais. Se você expõe um serviço gRPC via Nginx, precisa de HTTP/2 habilitado. Para gRPC no Nginx: use grpc_pass em vez de proxy_pass, e o bloco listen 443 ssl http2 é obrigatório.