Introdução

Quando construí nossa aplicação financeira no Tomcat, rapidamente percebi que colocar o Tomcat diretamente na Internet pública não era uma boa ideia. Funcionou no início, mas era frágil, difícil de proteger e quase impossível de manter de forma suave durante as implantações.

Eventualmente, decidi colocar o Nginx na frente do Tomcat e deixar o Nginx lidar com tudo que o Tomcat não é bom, especialmente a terminação SSL, modo de manutenção, cache de arquivos estáticos e ocultação de detalhes da infraestrutura interna.

Este artigo explica a configuração exata que uso em produção hoje. Não é um guia genérico. É escrito especificamente para o sistema financeiro que implantei, e inclui configurações reais e a lógica por trás de cada decisão.

Por que Precisava do Nginx na Frente do Tomcat

1. Uma página de manutenção limpa quando o Tomcat está reiniciando

Em um sistema financeiro, muitas vezes precisamos reiniciar o Tomcat durante implantações ou manutenção. Se o Tomcat estiver fora do ar, o usuário nunca deve ver uma página 503 bruta do Tomcat que expõe informações do servidor.

Com o Nginx, os usuários sempre veem uma página de manutenção amigável, mesmo que o Tomcat esteja completamente offline. O Nginx captura a resposta 502 ou 503 e serve uma página HTML estática que preparei.

2. SSL é muito mais fácil no Nginx

Configurar SSL dentro do Tomcat é desnecessariamente complicado. Você precisa converter certificados em um keystore Java, gerenciar o conector e lidar com múltiplos formatos.

Com o Nginx, o SSL é simples. Eu só preciso de dois arquivos, um certificado e uma chave privada. O Nginx termina o HTTPS, e o Tomcat só recebe HTTP simples do localhost. A renovação de certificados e a depuração também são mais fáceis.

3. Tomcat está completamente oculto do mundo exterior

Por razões de segurança, não quero que o Tomcat exponha suas portas ou informações do servidor para usuários públicos. O Tomcat só escuta em 127.0.0.1:8080.

Se alguém tentar escanear meu servidor, não conseguirá detectar que o Tomcat existe.

4. Cabeçalhos grandes para aprovações financeiras

Algumas operações de aprovação no sistema enviam uma longa lista de IDs de aplicações financeiras no cabeçalho ou na string de consulta.

Para suportar esses cabeçalhos grandes, configurei o Nginx para permitir buffers de cabeçalho maiores. Sem isso, algumas requisições falhariam porque o tamanho padrão do cabeçalho é muito pequeno.

5. Uploads de arquivos grandes

Os usuários fazem upload de contratos, faturas e documentos digitalizados. Eu defini um limite de tamanho de upload limpo no Nginx para que arquivos grandes não cheguem ao Tomcat, a menos que passem pela validação do Nginx primeiro.

6. Conteúdo estático mais rápido (CSS, JS, ícones)

Embora o Tomcat possa servir arquivos estáticos, o Nginx é muito mais rápido. Ativei o cache para ativos estáticos para que o Nginx os sirva diretamente sem incomodar o Tomcat.

7. Timeouts personalizados para operações de longa duração

Alguns processos em um sistema financeiro demoram mais, como geração de relatórios ou aprovação em lote.

O Nginx me dá controle total sobre os timeouts do proxy, para que os usuários não recebam erros 504 inesperados.

A Configuração HTTPS do Nginx que Uso

Eu mantenho este arquivo em:

/etc/nginx/sites-available/myapp_https

Aqui está a configuração real, simplificada para o artigo, mas ainda precisa ser precisa.

server {
    listen 443 ssl;
    server_name finance.example.com;

    ssl_certificate     /opt/myapp/keystore/app.crt;
    ssl_certificate_key /opt/myapp/keystore/app.key;

    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout 5m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;

    large_client_header_buffers 4 65k;
    client_max_body_size 100m;

    error_page 502 503 = @maintenance;
    error_page 404 = @errors;

    access_log /opt/myapp/nginx/logs/access.log;
    error_log  /opt/myapp/nginx/logs/error.log;

    location / {
        proxy_set_header Host                $host;
        proxy_set_header X-Forwarded-Host    $host;
        proxy_set_header X-Forwarded-Server  $host;
        proxy_set_header X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto   https;

        proxy_pass http://127.0.0.1:8080;

        proxy_buffering off;
        proxy_buffer_size 128k;
        proxy_buffers 100 128k;

        proxy_connect_timeout 180;
        proxy_send_timeout    180;
        proxy_read_timeout    180;
        send_timeout          180;

        location ~* \.(css|js|jpg|gif|ico)$ {
            proxy_cache cache;
            proxy_cache_key   $host$uri$is_args$args;
            proxy_cache_valid 200 301 302 30m;
            expires 30m;
            proxy_pass http://127.0.0.1:8080;
        }
    }

    location = / {
        return 301 /myapp/;
    }

    location @maintenance {
        root /opt/myapp/nginx/www;
        rewrite ^ /maintenance.html break;
    }

    location @errors {
        root /opt/myapp/nginx/www;
        rewrite ^ /404.html break;
    }
}

Este é o núcleo do sistema. O Nginx lida com SSL, encaminha o tráfego para o Tomcat, serve a página de manutenção quando o Tomcat está offline, faz cache de conteúdo estático e protege a estrutura da rede interna.

Redirecionamento HTTP (Porta 80)

Adicionei uma configuração simples que redireciona todo o tráfego HTTP para HTTPS.

/etc/nginx/sites-available/myapp_http
server {
    listen 80;
    server_name finance.example.com;
    return 301 https://$host$request_uri;
}

Estrutura de Pastas

Eu mantenho os arquivos relacionados ao Nginx dentro de uma pasta de aplicação dedicada:

/opt/myapp/
    keystore/
    nginx/
        logs/
        www/

Isso facilita a gestão de certificados, logs e páginas estáticas.

Configuração do Tomcat que Completa a Configuração

Dentro do server.xml do Tomcat, eu vinculo o Tomcat ao localhost para que não possa ser acessado de fora.

<Connector port="8080"
           address="127.0.0.1"
           maxHttpHeaderSize="65536"
           protocol="HTTP/1.1"
           connectionTimeout="20000"
           maxThreads="150"/>

Eu também faço o Tomcat entender o IP e o protocolo reais do cliente:

<Valve className="org.apache.catalina.valves.RemoteIpValve"
       remoteIpHeader="X-Forwarded-For"
       protocolHeader="X-Forwarded-Proto"
       protocolHeaderHttpsValue="https"/>

Isso garante que o sistema registre o IP correto do cliente e se comporte corretamente para HTTPS.

Por que Esta Configuração Funciona Bem para um Sistema Financeiro

Colocar o Nginx na frente do Tomcat fez com que todo o sistema parecesse muito mais profissional e estável. Durante implantações ou reinicializações, os usuários nunca encontram as típicas páginas 503 do Tomcat. Em vez disso, eles sempre veem uma tela de manutenção limpa, o que faz o sistema parecer confiável mesmo quando o trabalho está acontecendo nos bastidores.

Lidar com SSL no Nginx também simplifica tudo. Os certificados são mais fáceis de gerenciar, renovar e depurar, e o Tomcat não precisa mais lidar com HTTPS diretamente. Outro benefício é a segurança. Como o Tomcat só escuta no localhost, ele está completamente oculto do tráfego externo, o que elimina toda uma categoria de tentativas de escaneamento e sondagem.

O desempenho também melhora. Arquivos estáticos, como CSS e JavaScript, carregam mais rápido porque o Nginx pode armazená-los em cache, e os uploads são verificados e limitados antes de chegarem ao Tomcat. Algumas de nossas operações financeiras envolvem cabeçalhos grandes ou ações de longa duração, e o Nginx me dá controle total sobre tamanhos de buffer e timeouts, o que faz com que essas operações sejam executadas suavemente, sem erros aleatórios.

Mesmo em casos onde o Tomcat fica offline por um momento, o site ainda responde de forma previsível graças à página de manutenção. Ao longo dos anos, essa configuração provou ser extremamente sólida. Ela ajudou a aplicação financeira a alcançar quase zero de inatividade em muitas versões e mudanças de infraestrutura, e continua a lidar com o tráfego de produção sem surpresas.