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
    Dica
    HTTP/3 usa UDP na porta 443. Se houver firewall na frente bloqueando UDP (comum em redes corporativas), o browser automaticamente faz fallback para HTTP/2.

    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

    $ runstack deploy --plan starter

    Não quer configurar manualmente?

    Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.

    Perguntas frequentes