Pular para o conteúdo

Nginx proxy reverso com cache para WooCommerce em picos

Por Equipe Técnica AviraHost · 14 min de leitura · Atualizado em · nginx, proxy-reverso, woocommerce, cache, picos-de-acesso, debian-13, performance, AviraHost · 0

Nginx como proxy reverso com cache para WooCommerce é uma camada que fica à frente do servidor de aplicação (Apache ou outro Nginx com PHP-FPM) e entrega cópias prontas das páginas públicas da loja, evitando que cada visitante em um pico acione PHP e banco de dados. O cache sozinho não resolve tudo: sem regras de bypass para carrinho, checkout e usuários logados, ele quebra a loja. Para configurar corretamente no Debian 13, siga estes passos:

  1. Mova o servidor de aplicação (Apache ou Nginx + PHP-FPM) para a porta 8080, só em 127.0.0.1.
  2. Instale o Nginx 1.28+ e crie a zona de cache com proxy_cache_path.
  3. Defina um map que ativa o bypass para cookies e URLs do WooCommerce.
  4. Crie o bloco server com proxy_pass, TTL curto e proxy_cache_use_stale.
  5. Adicione o header X-Cache-Status e valide com curl -I.
  6. Simule carga e acompanhe HIT/MISS/BYPASS antes do pico real.

Pré-requisitos

  • Acesso root ou sudo a um VPS com Debian 13 (Trixie) ou Ubuntu 24.04 LTS.
  • WooCommerce em execução com PHP 8.4 atrás de Apache ou Nginx + PHP-FPM.
  • Nginx 1.28 ou superior (o pacote nginx do repositório oficial serve).
  • Certificado SSL válido para o domínio da loja (Let's Encrypt via Certbot, por exemplo).
  • DNS do domínio apontando para o IP do servidor e portas 80/443 liberadas no firewall.
  • Permalinks em português conhecidos: /carrinho/, /finalizar-compra/, /minha-conta/.

Nginx como proxy reverso com cache para WooCommerce: arquitetura

A arquitetura de proxy reverso com cache separa duas responsabilidades: o Nginx na frente responde às conexões do público, termina o TLS e serve páginas do disco; o backend na porta 8080 só é acionado quando a resposta não está em cache ou quando o visitante tem sessão de compra. Em um pico de Black Friday ou campanha de influenciador, 90% ou mais dos acessos caem em home, categorias e páginas de produto, e são justamente essas que o cache absorve.

Primeiro, mude o backend para escutar apenas localmente. No Apache, edite /etc/apache2/ports.conf:

Listen 127.0.0.1:8080

E ajuste o VirtualHost do site para <VirtualHost 127.0.0.1:8080>. Se o backend for outro Nginx com PHP-FPM, troque o listen 80; por listen 127.0.0.1:8080;. Reinicie e confirme:

sudo systemctl restart apache2
ss -tlnp | grep 8080
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:* users:(("apache2",pid=1842,fd=4))

Agora instale o Nginx frontal:

sudo apt update && sudo apt install -y nginx
nginx -v
nginx version: nginx/1.28.0

Se o site ainda não força HTTPS, consulte como redirecionar um site HTTP para HTTPS — o redirecionamento deve acontecer na camada do proxy, não no backend, para não gerar loops.

Configurar a zona de proxy_cache e as regras de bypass

A zona de cache do Nginx define onde os arquivos ficam, quanto espaço ocupam e por quanto tempo permanecem. Crie o arquivo /etc/nginx/conf.d/woo-cache.conf:

proxy_cache_path /var/cache/nginx/woo levels=1:2 keys_zone=woo:100m
                 max_size=2g inactive=30m use_temp_path=off;

map $http_cookie $woo_skip_cookie {
    default 0;
    ~*woocommerce_items_in_cart 1;
    ~*woocommerce_cart_hash 1;
    ~*wp_woocommerce_session_ 1;
    ~*wordpress_logged_in_ 1;
    ~*comment_author_ 1;
}

map $request_uri $woo_skip_uri {
    default 0;
    ~*^/carrinho/ 1;
    ~*^/finalizar-compra/ 1;
    ~*^/minha-conta/ 1;
    ~*^/wp-admin/ 1;
    ~*^/wp-login.php 1;
    ~*^/\?wc-ajax= 1;
    ~*^/wp-json/ 1;
    ~*\?add-to-cart= 1;
}

map "$woo_skip_cookie$woo_skip_uri$request_method" $woo_skip {
    default 1;
    "00GET" 0;
    "00HEAD" 0;
}

O terceiro map combina as condições: só GET e HEAD sem cookie de sessão e fora das URLs sensíveis recebem valor 0 (cacheável). Qualquer POST — inclusive o envio do formulário de pedido — passa direto. Crie o diretório e ajuste o dono:

sudo mkdir -p /var/cache/nginx/woo
sudo chown www-data:www-data /var/cache/nginx/woo

Agora o bloco server em /etc/nginx/sites-available/seudominio.com.br:

server {
    listen 443 ssl;
    http2 on;
    server_name seudominio.com.br www.seudominio.com.br;

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

    client_max_body_size 64m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_cache woo;
        proxy_cache_key "$scheme$host$request_uri";
        proxy_cache_valid 200 301 302 2m;
        proxy_cache_valid 404 30s;
        proxy_cache_bypass $woo_skip;
        proxy_no_cache $woo_skip;
        proxy_ignore_headers Cache-Control Expires Set-Cookie;
        proxy_hide_header Set-Cookie;

        proxy_cache_use_stale error timeout updating http_500 http_502 http_503;
        proxy_cache_background_update on;
        proxy_cache_lock on;
        proxy_cache_lock_timeout 5s;

        add_header X-Cache-Status $upstream_cache_status;
    }
}

server {
    listen 80;
    server_name seudominio.com.br www.seudominio.com.br;
    return 301 https://$host$request_uri;
}

Atenção: proxy_hide_header Set-Cookie só é aplicado a respostas que entram no cache; respostas com $woo_skip = 1 nunca são armazenadas, então o cookie de sessão chega normalmente ao cliente. Se você remover o proxy_no_cache, uma página de carrinho pode ser gravada e entregue a outro visitante — esse é o vazamento clássico de dados em lojas mal configuradas.

No wp-config.php, garanta que o WordPress reconheça o HTTPS vindo do proxy:

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

Valide e recarregue:

sudo nginx -t && sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Testar o cache HTTP sob carga antes do pico

Testar o cache HTTP antes do evento evita descobrir problemas com clientes reais. Faça duas requisições seguidas à home:

curl -sI https://seudominio.com.br/ | grep -i x-cache
curl -sI https://seudominio.com.br/ | grep -i x-cache
X-Cache-Status: MISS
X-Cache-Status: HIT

Agora simule um visitante com carrinho e uma URL de checkout:

curl -sI -H "Cookie: woocommerce_items_in_cart=1" https://seudominio.com.br/ | grep -i x-cache
curl -sI https://seudominio.com.br/finalizar-compra/ | grep -i x-cache
X-Cache-Status: BYPASS
X-Cache-Status: BYPASS

Para medir o ganho real de TTFB, compare o tempo até o primeiro byte entre MISS e HIT:

curl -so /dev/null -w "TTFB: %{time_starttransfer}s\n" https://seudominio.com.br/produto/camiseta-basica/

Em um VPS de 2 vCPUs, ao rodar este comando você normalmente verá o MISS na faixa de centenas de milissegundos e o HIT abaixo de 50 ms, porque o Nginx lê o arquivo do disco sem acionar PHP. Para estressar, instale o wrk ou ab e dispare conexões concorrentes contra uma categoria enquanto observa htop: com o cache ativo, o uso de CPU dos processos PHP-FPM praticamente não deve se mover. Se o backend subir junto com a carga, o bypass está pegando mais do que deveria — verifique cookies de plugins de analytics ou de consentimento que podem estar listados no map.

Com TTL de 2 minutos e proxy_cache_lock, quando a cópia expira apenas uma requisição vai ao backend; as demais aguardam ou recebem a versão stale. Esse comportamento é o que impede o efeito manada (cache stampede) no momento em que todo mundo abre a mesma página de oferta. Se a loja cresceu além do que um único servidor aguenta, vale avaliar a diferença entre hospedagem de sites e VPS para decidir onde cada camada deve rodar.

Problemas comuns e como resolver

Sintoma: produto adicionado ao carrinho não aparece ou carrinho de outro cliente é exibido

Causa: alguma rota do WooCommerce está sendo cacheada — geralmente ?wc-ajax=get_refreshed_fragments ou o cookie woocommerce_items_in_cart não foi detectado porque o map usa comparação exata em vez de regex.
Solução: confirme que as entradas do map começam com ~*, esvazie o cache com rm -rf /var/cache/nginx/woo/* e recarregue o Nginx. Teste novamente com curl enviando o cookie.

Sintoma: redirecionamento infinito ou "mixed content" após ativar o proxy

Causa: o backend recebe a requisição em HTTP na porta 8080 e o WordPress acredita que o site está sem SSL, forçando redirect para HTTPS, que volta ao proxy, que repete o ciclo.
Solução: adicione o trecho de HTTP_X_FORWARDED_PROTO no wp-config.php, mantenha proxy_set_header X-Forwarded-Proto https e remova qualquer RewriteRule de redirecionamento HTTPS do .htaccess.

Sintoma: X-Cache-Status sempre MISS, nunca HIT

Causa: o backend envia Set-Cookie ou Cache-Control: no-cache em toda resposta (plugin de sessão, PHP session_start ou tema com cookie de idioma), e o Nginx recusa gravar.
Solução: mantenha proxy_ignore_headers Cache-Control Expires Set-Cookie e identifique com curl -I http://127.0.0.1:8080/ -H "Host: seudominio.com.br" qual plugin está emitindo o cookie para visitantes anônimos; desative-o ou restrinja-o.

Sintoma: erro 502 Bad Gateway em horários de pico

Causa: o pool do PHP-FPM esgotou pm.max_children e o Apache parou de responder na 8080, ou o Nginx atingiu o limite de descritores de arquivo.
Solução: ative proxy_cache_use_stale http_502 (já presente no exemplo) para servir a cópia antiga enquanto o backend se recupera, aumente worker_rlimit_nofile e revise o dimensionamento do PHP-FPM com base na RAM disponível.

Perguntas frequentes sobre Nginx como proxy reverso com cache para WooCommerce

O cache do proxy reverso quebra o carrinho e o checkout do WooCommerce?

Quebra apenas se você cachear tudo indiscriminadamente. A configuração correta ignora o cache quando existem cookies como woocommerce_items_in_cart, woocommerce_cart_hash, wp_woocommerce_session_* e wordpress_logged_in_*, além de excluir as URLs /carrinho/, /finalizar-compra/, /minha-conta/ e /wp-admin/. Assim o visitante anônimo recebe a página cacheada e quem tem carrinho ativo passa direto ao PHP.

Qual a diferença entre proxy_cache e fastcgi_cache no Nginx para WooCommerce?

O fastcgi_cache guarda a resposta do PHP-FPM quando o próprio Nginx conversa diretamente com o PHP. O proxy_cache funciona na camada de proxy reverso, guardando respostas de um backend HTTP (Apache, outro Nginx ou container), o que permite separar a camada de cache da camada de aplicação e absorver picos antes do tráfego chegar ao WordPress. Ambos aceitam as mesmas regras de bypass por cookie e URL.

Como limpar o cache do Nginx após atualizar produtos ou preços na loja?

A forma mais simples é remover o diretório de cache com rm -rf /var/cache/nginx/woo/* e recarregar o Nginx com systemctl reload nginx, o que esvazia tudo sem derrubar conexões. Para invalidação seletiva, use um plugin de cache no WordPress compatível com purge por URL ou configure proxy_cache_bypass com um header secreto. Em picos, prefira TTLs curtos (1 a 5 minutos) em vez de limpar manualmente.

Quanto tempo de cache usar para páginas do WooCommerce em picos de acesso?

Para home, categorias e páginas de produto, um TTL entre 60 segundos e 5 minutos já reduz drasticamente a carga no PHP e no banco, pois milhares de visitantes simultâneos passam a receber a mesma cópia. Ative proxy_cache_use_stale e proxy_cache_background_update para servir conteúdo levemente desatualizado enquanto o Nginx renova a cópia em segundo plano, evitando que todos os pedidos cheguem ao backend ao mesmo tempo.

Como saber se a página está sendo servida do cache do proxy reverso?

Adicione o header add_header X-Cache-Status $upstream_cache_status no bloco server e consulte com curl -I https://seudominio.com.br/. O valor HIT indica resposta vinda do cache, MISS indica que foi buscada no backend e BYPASS mostra que uma regra de exclusão (cookie de carrinho ou URL de checkout) foi acionada. Comparar o TTFB entre HIT e MISS confirma o ganho real.

Conclusão

  • Coloque o backend em 127.0.0.1:8080 e deixe o Nginx 1.28 na frente com proxy_cache, TTL de 1 a 5 minutos e proxy_cache_lock para evitar o efeito manada.
  • Trate o bypass por cookie e URL como regra de segurança, não como otimização: sem ele, carrinhos e dados de clientes podem vazar entre sessões.
  • Valide HIT, MISS e BYPASS com curl e um teste de carga antes de qualquer campanha — o pico não é hora de descobrir que o cache estava desligado.

Leia também

Precisa de ajuda com Nginx e WooCommerce em picos de acesso?

Um VPS com recursos dedicados e acesso root permite separar proxy, aplicação e banco exatamente como descrito aqui, com a flexibilidade de ampliar CPU e memória antes de uma campanha. A equipe da AviraHost pode orientar o dimensionamento adequado para a sua loja.

Conhecer os planos de Servidor VPS


Esta resposta foi útil?