Como Configurar Nginx para WordPress

Tutorial completo para configurar Nginx com WordPress. Server blocks, PHP-FPM, cache, SSL, segurança e otimização de performance.

O Nginx é um dos servidores web mais rápidos e eficientes do mercado. Enquanto o Apache dominou a web por décadas, o Nginx se tornou a escolha preferida para sites de alta performance, incluindo WordPress.

Neste tutorial completo, você vai aprender a instalar e configurar o Nginx para rodar WordPress de forma otimizada, com PHP-FPM, cache, SSL e todas as boas práticas de segurança e performance.


Nginx vs Apache: Por Que Escolher Nginx

Antes de mergulhar na configuração, vale entender por que o Nginx é uma excelente escolha para WordPress.

Arquitetura

  • Apache: cria um processo ou thread para cada conexão simultânea. Sob alta carga, o consumo de memória cresce rapidamente.
  • Nginx: usa uma arquitetura event-driven com um número fixo de worker processes. Cada worker lida com milhares de conexões simultâneas sem criar processos adicionais.

Performance

  • Arquivos estáticos: Nginx serve arquivos estáticos (CSS, JS, imagens) até 2x mais rápido que o Apache
  • Uso de memória: Nginx consome significativamente menos memória sob carga
  • Conexões simultâneas: Nginx lida com 10.000+ conexões sem degradação perceptível

Quando o Apache ainda faz sentido

  • Hospedagem compartilhada com .htaccess (Nginx não suporta .htaccess)
  • Plugins que dependem de regras mod _ rewrite específicas do Apache
  • Ambientes onde a simplicidade de configuração é prioridade

Para WordPress em VPS ou servidor dedicado, o Nginx é a escolha recomendada.


Instalando Nginx no Ubuntu

Este tutorial usa Ubuntu 22.04/24.04 LTS, a distribuição mais comum para servidores web.

Atualizar o sistema

sudo apt update && sudo apt upgrade -y

Instalar o Nginx

sudo apt install nginx -y

Verificar a instalação

sudo systemctl status nginx
nginx -v

Iniciar e habilitar no boot

sudo systemctl start nginx
sudo systemctl enable nginx

Configurar o firewall

# Permitir tráfego HTTP e HTTPS
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

Neste ponto, ao acessar o IP do servidor no navegador, você deve ver a página padrão do Nginx.


Instalando PHP-FPM

O WordPress precisa de PHP para funcionar. Com Nginx, usamos PHP-FPM (FastCGI Process Manager) para processar scripts PHP.

Instalar PHP e módulos necessários

sudo apt install php8.2-fpm php8.2-mysql php8.2-curl php8.2-gd \
  php8.2-mbstring php8.2-xml php8.2-zip php8.2-intl \
  php8.2-imagick php8.2-opcache php8.2-soap php8.2-bcmath -y

Verificar a instalação

php -v
sudo systemctl status php8.2-fpm

Configurar o PHP-FPM

Edite o arquivo de configuração do pool:

sudo nano /etc/php/8.2/fpm/pool.d/www.conf

Configurações recomendadas para um VPS com 4-8GB de RAM:

; Modo de gerenciamento de processos
pm = dynamic

; Número máximo de processos filhos
pm.max_children = 25

; Processos iniciais
pm.start_servers = 5

; Mínimo de processos ociosos
pm.min_spare_servers = 3

; Máximo de processos ociosos
pm.max_spare_servers = 10

; Requests antes de reciclar o processo (previne memory leaks)
pm.max_requests = 500

; Timeout para processos lentos
request_terminate_timeout = 300

Configurar o php.ini

sudo nano /etc/php/8.2/fpm/php.ini

Configurações recomendadas para WordPress:

upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
max_input_time = 300
max_input_vars = 3000

Reiniciar PHP-FPM

sudo systemctl restart php8.2-fpm

Server Block para WordPress

O "server block" do Nginx é equivalente ao "virtual host" do Apache. Aqui configuramos como o Nginx vai servir o site WordPress.

Criar o server block

sudo nano /etc/nginx/sites-available/seusite.com.br

Configuração básica funcional:

server {
    listen 80;
    listen [::]:80;
    server_name seusite.com.br www.seusite.com.br;
    root /var/www/seusite.com.br;
    index index.php index.html;

    # Logs
    access_log /var/log/nginx/seusite-access.log;
    error_log /var/log/nginx/seusite-error.log;

    # Tamanho máximo de upload
    client_max_body_size 64M;

    # Rewrite de permalinks do WordPress
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # Processar PHP via PHP-FPM
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_read_timeout 300;
    }

    # Bloquear acesso a arquivos ocultos
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Cache de arquivos estáticos
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|webp|avif|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # Bloquear acesso ao wp-config.php
    location = /wp-config.php {
        deny all;
    }

    # Bloquear acesso ao xmlrpc.php (alvo frequente de ataques)
    location = /xmlrpc.php {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Bloquear listagem de diretórios
    autoindex off;
}

Ativar o server block

# Criar link simbólico
sudo ln -s /etc/nginx/sites-available/seusite.com.br /etc/nginx/sites-enabled/

# Remover o site padrão (opcional)
sudo rm /etc/nginx/sites-enabled/default

# Testar a configuração
sudo nginx -t

# Recarregar o Nginx
sudo systemctl reload nginx

No Apache, os permalinks do WordPress são configurados via .htaccess . No Nginx, usamos a diretiva try_files no server block.

A linha chave é:

location / {
    try_files $uri $uri/ /index.php?$args;
}

Essa regra faz o seguinte:

  1. Tenta servir o arquivo diretamente ( $uri )
  2. Tenta servir como diretório ( $uri/ )
  3. Se nenhum dos dois existe, encaminha para index.php com os argumentos (query string)

Isso é tudo que o WordPress precisa para que os permalinks bonitos funcionem (ex: /meu-post/ em vez de /?p=123 ).

Configuração no WordPress

Após configurar o Nginx, acesse Configurações > Links Permanentes no painel do WordPress e selecione a estrutura desejada (recomendado: "Nome do post" ou estrutura personalizada /%postname%/ ).


Headers de Segurança

Headers HTTP de segurança protegem seu site contra diversos tipos de ataques. Adicione-os dentro do bloco server :

# Headers de segurança
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

# Content Security Policy (ajuste conforme necessário)
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;

O CSP (Content Security Policy) está comentado porque pode quebrar plugins e temas que usam scripts inline. Habilite e ajuste conforme necessário.

Proteções adicionais no server block

# Bloquear acesso a arquivos sensíveis
location ~* /(wp-config\.php|readme\.html|license\.txt|wp-includes/.*\.php) {
    deny all;
}

# Bloquear execução de PHP em diretórios de upload
location ~* /wp-content/uploads/.*\.php$ {
    deny all;
}

# Limitar métodos HTTP aceitos
if ($request_method !~ ^(GET|HEAD|POST)$) {
    return 444;
}

Cache com FastCGI Cache

O FastCGI Cache do Nginx é uma das formas mais eficientes de cache para WordPress. Ele armazena a resposta PHP completa em disco e serve diretamente, sem passar pelo PHP-FPM.

Configurar a zona de cache

No arquivo principal do Nginx ( /etc/nginx/nginx.conf ), dentro do bloco http :

http {
    # Definir zona de cache
    fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2
        keys_zone=WORDPRESS:100m
        inactive=60m
        max_size=512m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    fastcgi_cache_use_stale error timeout updating http_500 http_503;
    fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
}

Adicionar cache ao server block

server {
    # Variáveis de controle do cache
    set $skip_cache 0;

    # Não cachear requisições POST
    if ($request_method = POST) {
        set $skip_cache 1;
    }

    # Não cachear URLs com query strings
    if ($query_string != "") {
        set $skip_cache 1;
    }

    # Não cachear páginas do admin, login, carrinho e checkout
    if ($request_uri ~* "/wp-admin/|/wp-login.php|/xmlrpc.php|/cart/|/checkout/|/my-account/") {
        set $skip_cache 1;
    }

    # Não cachear para usuários logados ou com itens no carrinho
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|woocommerce_items_in_cart") {
        set $skip_cache 1;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        # Configuração do cache
        fastcgi_cache WORDPRESS;
        fastcgi_cache_valid 200 301 302 60m;
        fastcgi_cache_valid 404 1m;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;

        # Header para debug (remova em produção)
        add_header X-FastCGI-Cache $upstream_cache_status;
    }
}

Criar o diretório de cache

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

Limpar o cache

# Limpar todo o cache
sudo rm -rf /var/cache/nginx/fastcgi/*

# Ou use o plugin Nginx Helper no WordPress para limpar
# automaticamente quando conteúdo é atualizado

SSL com Let's Encrypt e Certbot

HTTPS é obrigatório para qualquer site moderno. O Let's Encrypt oferece certificados SSL gratuitos, e o Certbot automatiza a instalação e renovação.

Instalar o Certbot

sudo apt install certbot python3-certbot-nginx -y

Obter o certificado

sudo certbot --nginx -d seusite.com.br -d www.seusite.com.br

O Certbot vai:

  1. Verificar a propriedade do domínio
  2. Obter o certificado SSL
  3. Configurar o Nginx automaticamente para HTTPS
  4. Adicionar redirecionamento HTTP para HTTPS

Verificar a renovação automática

# Testar renovação
sudo certbot renew --dry-run

# Verificar o timer do systemd
sudo systemctl status certbot.timer

O Certbot configura automaticamente a renovação. Os certificados Let's Encrypt expiram a cada 90 dias, mas o Certbot os renova automaticamente.

Configuração SSL otimizada

Após o Certbot gerar a configuração, melhore a segurança SSL adicionando ao server block HTTPS:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name seusite.com.br www.seusite.com.br;

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

    # Protocolos e cifras
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    # HSTS (forçar HTTPS por 1 ano)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # Session
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # ... resto da configuração do site
}

# Redirecionar HTTP para HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name seusite.com.br www.seusite.com.br;
    return 301 https://$server_name$request_uri;
}

Compressão Gzip

Gzip comprime as respostas do servidor antes de enviá-las ao navegador, reduzindo significativamente o tráfego.

Adicione ao bloco http no /etc/nginx/nginx.conf :

# Compressão Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types
    text/plain
    text/css
    text/javascript
    text/xml
    application/json
    application/javascript
    application/xml
    application/xml+rss
    application/x-javascript
    application/vnd.ms-fontobject
    font/opentype
    image/svg+xml
    image/x-icon;

Brotli (alternativa mais eficiente)

Se quiser compressão ainda melhor, instale o módulo Brotli:

sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static -y
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/javascript application/json
    application/javascript application/xml image/svg+xml;

Otimização de Performance

Worker processes e conexões

No /etc/nginx/nginx.conf :

# Número de workers = número de CPUs
worker_processes auto;

# Número máximo de conexões por worker
events {
    worker_connections 2048;
    multi_accept on;
    use epoll;
}

http {
    # Keepalive
    keepalive_timeout 30;
    keepalive_requests 100;

    # Buffers
    client_body_buffer_size 16K;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 16k;

    # Timeouts
    client_body_timeout 12;
    client_header_timeout 12;
    send_timeout 10;

    # Sendfile (servir arquivos diretamente do kernel)
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    # Desativar exibição da versão do Nginx
    server_tokens off;

    # Limitar taxa de requisições (proteção contra DDoS básico)
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
}

Open file cache

open_file_cache max=10000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

Problemas Comuns e Debug

Erro 502 Bad Gateway

Significa que o Nginx não consegue se comunicar com o PHP-FPM.

Verificações:

# PHP-FPM está rodando?
sudo systemctl status php8.2-fpm

# O socket existe?
ls -la /var/run/php/php8.2-fpm.sock

# Logs do PHP-FPM
sudo tail -f /var/log/php8.2-fpm.log

Erro 403 Forbidden

Geralmente um problema de permissões:

# Corrigir permissões do WordPress
sudo chown -R www-data:www-data /var/www/seusite.com.br/
sudo find /var/www/seusite.com.br/ -type f -exec chmod 644 {} \;
sudo find /var/www/seusite.com.br/ -type d -exec chmod 755 {} \;

Erro 404 em todas as páginas (exceto home)

Os permalinks não estão configurados corretamente. Verifique se o try_files está presente:

location / {
    try_files $uri $uri/ /index.php?$args;
}

Upload falha com erro de tamanho

Ajuste o client_max_body_size no server block:

client_max_body_size 64M;

E também no php.ini :

upload_max_filesize = 64M
post_max_size = 64M

Testar e recarregar a configuração

Sempre teste antes de recarregar:

# Testar configuração
sudo nginx -t

# Recarregar (sem downtime)
sudo systemctl reload nginx

# Reiniciar (com breve downtime)
sudo systemctl restart nginx

Monitoramento

Habilitar o status do Nginx

# Adicione ao server block ou em um bloco separado
location /nginx_status {
    stub_status on;
    allow 127.0.0.1;
    deny all;
}

Monitorar logs em tempo real

# Access log
sudo tail -f /var/log/nginx/seusite-access.log

# Error log
sudo tail -f /var/log/nginx/seusite-error.log

# Requisições por segundo
sudo tail -f /var/log/nginx/seusite-access.log | awk '{print $4}' | uniq -c

Ferramentas de monitoramento

  • Netdata: monitoramento em tempo real do servidor, Nginx e PHP-FPM
  • GoAccess: análise de logs do Nginx em terminal ou HTML
  • Munin: gráficos históricos de performance

Leia Também


Conclusão

Configurar Nginx para WordPress exige mais passos manuais do que o Apache, mas o resultado em performance e eficiência compensa o esforço. Com PHP-FPM otimizado, FastCGI Cache, SSL via Let's Encrypt e compressão gzip, seu site WordPress vai carregar significativamente mais rápido.

Lembre-se de sempre testar a configuração ( nginx -t ) antes de recarregar e mantenha backups das configurações funcionais.

Precisa de ajuda para configurar e otimizar o servidor do seu WordPress? A HOSTWP cuida de tudo, do servidor ao site. Nossa equipe configura Nginx, PHP-FPM, cache, SSL e toda a infraestrutura para que seu site tenha performance máxima e segurança de nível profissional. Entre em contato e deixe o servidor com quem entende.

Artigos relacionados