kb.erickguedes.com
Nginx: Performance e Proxy Reverso

SSL/TLS e Cache

Aula 3 de 6

SSL/TLS no Nginx

Configuração Básica SSL

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name site.exemplo.com;

    # Certificados
    ssl_certificate     /etc/nginx/ssl/site.crt;
    ssl_certificate_key /etc/nginx/ssl/site.key;

    root /var/www/site;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

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

SSL com Let's Encrypt

# Instalar Certbot
sudo apt install certbot python3-certbot-nginx -y

# Obter certificado (modo Nginx)
sudo certbot --nginx -d site.exemplo.com -d www.site.exemplo.com

# Obter certificado (apenas arquivos)
sudo certbot certonly --nginx -d site.exemplo.com

# Listar certificados
sudo certbot certificates

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

# Verificar timer de renovação
sudo systemctl list-timers | grep certbot

Configuração SSL Moderna (A+)

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name site.exemplo.com;

    # Certificados Let's Encrypt
    ssl_certificate     /etc/letsencrypt/live/site.exemplo.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/site.exemplo.com/privkey.pem;

    # Protocolos: apenas TLS 1.2 e 1.3
    ssl_protocols TLSv1.2 TLSv1.3;

    # Ciphers modernos
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # DHCP (Elliptic Curve Diffie-Hellman)
    ssl_ecdh_curve X25519:secp384r1;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/site.exemplo.com/chain.pem;

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

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Outros headers de segurança
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options SAMEORIGIN always;
    add_header X-XSS-Protection "1; mode=block" always;
}
# Gerar parâmetros DH (Diffie-Hellman)
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

HTTP/2

server {
    # Habilitar HTTP/2 (basta adicionar http2)
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name site.exemplo.com;

    # HTTP/2 otimizações
    http2_max_concurrent_streams 128;
    http2_max_field_size 4k;
    http2_max_header_size 16k;

    # Priorização de streams
    location / {
        http2_push /style.css;
        http2_push /script.js;
    }
}
# Verificar se HTTP/2 está ativo
curl -I --http2 https://site.exemplo.com
# Ou com openssl:
openssl s_client -connect site.exemplo.com:443 -alpn h2 -quiet

HSTS e OCSP Stapling

server {
    # OCSP Stapling (envia status do certificado na handshake)
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/site.exemplo.com/chain.pem;

    # Resolver DNS para consultas OCSP
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # HSTS - enviar apenas em HTTPS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}

Cache com proxy_cache

Configuração Básica

# No bloco http (nginx.conf)
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache_zone:10m
                 max_size=1g inactive=60m use_temp_path=off;

# No server/location
server {
    location / {
        proxy_pass http://backend;
        proxy_cache cache_zone;
        proxy_cache_valid 200 302 60m;
        proxy_cache_valid 404 1m;
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503;
        proxy_cache_background_update on;
        proxy_cache_lock on;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

Cache Avançado

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m
                 max_size=1g inactive=60m use_temp_path=off;

server {
    location /api/ {
        proxy_pass http://api_backend;
        proxy_cache api_cache;

        # Cache por método e query string
        proxy_cache_methods GET HEAD;
        proxy_cache_key "$scheme$request_method$host$request_uri";

        # Tempo de cache por código de status
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 301 1h;
        proxy_cache_valid 404 1m;
        proxy_cache_valid any 1m;

        # Bypass do cache
        proxy_cache_bypass $http_cache_control;
        proxy_no_cache $http_pragma $http_authorization;

        # Stale content (servir cache expirado se backend falhar)
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        proxy_cache_background_update on;
        proxy_cache_lock on;
        proxy_cache_lock_timeout 5s;

        # Headers de cache
        add_header X-Cache-Status $upstream_cache_status;
        add_header X-Cache-Key $upstream_cache_key;

        # Ignorar headers de cache do backend
        proxy_ignore_headers Cache-Control Expires Set-Cookie;
    }
}

FastCGI Cache (PHP)

# No bloco http
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=php_cache:10m
                   max_size=1g inactive=60m;

server {
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;

        fastcgi_cache php_cache;
        fastcgi_cache_valid 200 60m;
        fastcgi_cache_use_stale error timeout updating;
        fastcgi_cache_methods GET HEAD;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";

        # Bypass para cookies de sessão
        fastcgi_cache_bypass $cookie_session;
        fastcgi_no_cache $cookie_session;

        add_header X-FastCGI-Cache $upstream_cache_status;
    }
}

Microcaching

# Microcaching: cache de curta duração para conteúdo dinâmico
proxy_cache_path /var/cache/nginx/micro levels=1:2 keys_zone=micro:10m
                 max_size=500m inactive=5m;

server {
    location / {
        proxy_pass http://backend;

        # Microcaching: cache de 1 segundo
        proxy_cache micro;
        proxy_cache_valid 200 1s;
        proxy_cache_use_stale updating;

        # Atualizar cache em background
        proxy_cache_background_update on;
        proxy_cache_lock on;

        # Cache key incluindo query string
        proxy_cache_key "$scheme$request_method$host$request_uri";

        add_header X-Micro-Cache $upstream_cache_status;
    }
}

Cache Purge

# Instalar módulo de cache purge (nginx-extras)
sudo apt install nginx-extras -y
# No bloco http
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache_purge:10m
                 max_size=1g purge;

server {
    location ~ /purge(/.*) {
        # Restringir purge a IPs internos
        allow 127.0.0.1;
        allow 192.168.1.0/24;
        deny all;

        proxy_cache_purge cache_purge $scheme$request_method$host$1;
    }
}
# Purgar cache de uma URL específica
curl -X PURGE http://localhost/purge/api/users
curl -X PURGE http://localhost/purge/style.css

# Purgar todo o cache
sudo rm -rf /var/cache/nginx/*
sudo systemctl reload nginx

Lab: Site com HTTPS e Cache Inteligente

Configure um site completo com SSL A+, HTTP/2, caching e microcaching.

# 1. Criar diretórios
sudo mkdir -p /var/www/ssl-site/{public,api}
echo "<h1>Site com SSL e Cache</h1>" | sudo tee /var/www/ssl-site/public/index.html
echo '{"status":"ok"}' | sudo tee /var/www/ssl-site/api/data.json

# 2. Gerar certificado auto-assinado (dev)
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/nginx/ssl/site.key \
    -out /etc/nginx/ssl/site.crt \
    -subj "/CN=ssl-site.local"

# 3. Gerar parâmetros DH
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

# 4. Criar diretório de cache
sudo mkdir -p /var/cache/nginx/{proxy,fastcgi,micro}

# 5. Criar configuração completa
cat << 'NGINX' | sudo tee /etc/nginx/sites-available/ssl-cache-site
# Cache paths
proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=main_cache:10m max_size=1g inactive=60m;
proxy_cache_path /var/cache/nginx/micro levels=1:2 keys_zone=micro_cache:5m max_size=500m inactive=5m;

# Redirect HTTP -> HTTPS
server {
    listen 80;
    server_name ssl-site.local;
    return 301 https://$server_name$request_uri;
}

# HTTPS server
server {
    listen 443 ssl http2;
    server_name ssl-site.local;

    # SSL
    ssl_certificate /etc/nginx/ssl/site.crt;
    ssl_certificate_key /etc/nginx/ssl/site.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000" always;

    # Root
    root /var/www/ssl-site/public;
    index index.html;

    # Conteúdo estático com cache longo
    location / {
        try_files $uri $uri/ =404;

        # Cache do navegador
        expires 1h;
        add_header Cache-Control "public, must-revalidate";
    }

    # Assets com cache máximo
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
        log_not_found off;
    }

    # API com microcaching
    location /api/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;

        proxy_cache micro_cache;
        proxy_cache_valid 200 1s;
        proxy_cache_use_stale updating;
        proxy_cache_background_update on;
        proxy_cache_lock on;
        proxy_cache_key "$scheme$request_method$host$request_uri";

        add_header X-Cache-Status $upstream_cache_status;
    }

    access_log /var/log/nginx/ssl-site-access.log;
    error_log /var/log/nginx/ssl-site-error.log;
}
NGINX

# 6. Habilitar e testar
sudo ln -sf /etc/nginx/sites-available/ssl-cache-site /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

# 7. Testar HTTPS
curl -k https://ssl-site.local
curl -kI https://ssl-site.local | grep -E "HTTP|strict-transport"
curl -kI https://ssl-site.local/style.css | grep -E "cache|expires"

Cache bem configurado reduz a latência em ordens de grandeza e diminui drasticamente a carga no backend. Combine cache no navegador (expires), cache no proxy (proxy_cache) e microcaching para conteúdo dinâmico para uma estratégia completa.