Voltar para o blog

    Os desafios reais de gerenciar certificados em servidores web: Nginx, Apache e Tomcat

    Palomino

    Emitir um certificado é a parte fácil. O que quebra site em produção é o que acontece depois: instalar o certificado no servidor web, montar a cadeia corretamente, e — o mais subestimado de todos — fazer o servidor efetivamente passar a usar o certificado novo.

    Cada servidor web tem seu próprio conjunto de armadilhas. O que funciona no Nginx não se aplica ao Tomcat. O que é padrão no Apache mudou entre versões. E boa parte desses problemas não gera erro no momento da renovação — eles aparecem depois, quando um cliente reporta que o site está "inseguro" e você descobre que o certificado novo nunca chegou a ser servido.

    Este artigo reúne os problemas concretos que times de infraestrutura enfrentam em cada servidor, com base em incidentes reais documentados.

    Nginx: o certificado renova, mas o servidor continua servindo o antigo

    Este é provavelmente o problema mais comum e mais traiçoeiro de todos. O certbot roda, o arquivo novo é escrito no disco, o script de renovação reporta sucesso — e o Nginx continua apresentando o certificado antigo.

    A causa é arquitetural. O Nginx carrega os certificados no momento em que faz o parse da configuração. Os workers apresentam o que o processo master carregou na inicialização ou no último reload. Substituir o arquivo PEM no disco não muda o que os workers ativos apresentam — só um reload ou restart puxa o material novo para a memória.

    O detalhe que pega muita gente: se a linha da configuração que aponta para o certificado não muda, o Nginx não recarrega o certificado. O arquivo antigo no caminho é sobrescrito pelo novo, mas o servidor continua usando o certificado da memória. Em alguns ambientes, administradores relataram que nem nginx -s reload, nem systemctl reload nginx, nem /etc/init.d/nginx reload carregam o certificado novo — só um restart completo do serviço resolve.

    Há ainda um agravante silencioso: se um reload falha, o Nginx continua servindo com a configuração anterior, que ainda tem o certificado expirado. E como os workers antigos continuam até suas conexões drenarem, mesmo depois de um reload bem-sucedido conexões de longa duração podem apresentar brevemente o certificado antigo.

    O resultado prático: você acha que renovou, seu monitoramento de arquivo diz que o certificado no disco é novo, e ainda assim os usuários veem um certificado expirado. Sem uma verificação que compare o que está sendo servido (não o que está no disco), esse gap passa despercebido até virar incidente.

    Apache: a cadeia de intermediários e a mudança que quebrou configs

    O problema número um do Apache não é o certificado em si — é a cadeia. A falha de configuração de SSL mais frequente é a ausência de um certificado intermediário: o certificado leaf está instalado, mas o intermediário da CA não está sendo servido junto.

    O que torna esse erro perigoso é que ele não aparece para você. Navegadores desktop costumam cachear intermediários — se um site anterior usou a mesma CA intermediária, o navegador já a tem e não percebe a ausência. Mas navegadores mobile não cacheiam: iOS Safari, Chrome no Android em instalação limpa e a maioria dos clientes mobile falham imediatamente se o intermediário estiver ausente na resposta do servidor. Ou seja: funciona no seu Chrome, quebra no celular do cliente.

    Para complicar, a forma correta de configurar isso mudou entre versões do Apache. A partir do Apache 2.4.8, a diretiva SSLCertificateChainFile foi descontinuada. A maneira moderna recomendada é incluir os certificados intermediários diretamente no arquivo especificado pela diretiva SSLCertificateFile, concatenando leaf + intermediários. Configs escritas para versões antigas, copiadas para servidores novos, silenciosamente param de carregar a cadeia — em versões mais novas, o Apache pode simplesmente ignorar o SSLCertificateChainFile e carregar apenas o que está no SSLCertificateFile.

    E há a armadilha da ordem. Um erro comum é colocar os certificados na ordem inversa (root primeiro, leaf por último). Isso não funciona: o leaf tem que vir sempre primeiro. Um arquivo de cadeia montado na ordem errada produz uma config que parece correta mas serve uma cadeia inválida.

    Tomcat: o mundo Java tem suas próprias regras

    Se você vem de Nginx e Apache, o Tomcat é outro planeta — porque ele não trabalha com arquivos PEM soltos, mas com keystores. O Tomcat opera apenas com keystores nos formatos JKS, PKCS11 ou PKCS12. O JKS é o formato padrão "Java KeyStore", criado pela ferramenta keytool. O PKCS12 é um padrão da internet, manipulável via OpenSSL, entre outros.

    Isso cria uma classe inteira de problemas que não existe nos outros servidores:

    Incompatibilidade de tipo de keystore. Um erro clássico: gerar o keystore em PKCS12 mas o Tomcat esperar JKS (ou vice-versa). O sintoma histórico é o Tomcat falhar ao subir com um java.io.IOException. Em um caso documentado, a solução foi justamente que o tipo de keystore padrão estava configurado como JKS no java.security, enquanto o keystore usado era PKCS12 — bastou alinhar os dois para funcionar.

    Cadeia dentro do keystore. No Tomcat, os intermediários precisam estar dentro do keystore, não em um arquivo separado. Ao gerar o PKCS12 via OpenSSL, omitir a flag -chain gera um keystore sem a cadeia completa — e o servidor sobe, mas serve uma cadeia incompleta, reproduzindo o mesmo problema do Apache por um caminho diferente.

    Sensibilidade a alias. Cada entrada no keystore é identificada por uma string de alias. Embora muitas implementações tratem aliases de forma case-insensitive, algumas são case-sensitive — o PKCS11, por exemplo, exige aliases case-sensitive. Por isso não é recomendado usar aliases que diferem apenas na caixa.

    O resultado é que renovar um certificado no Tomcat não é "substituir um arquivo". É reconstruir um keystore com o formato certo, a cadeia certa e o alias certo, e reiniciar o serviço — um processo com muito mais pontos de falha do que o cp + reload dos outros servidores.

    O padrão comum: renovar não é a mesma coisa que implantar

    Repare no que os três casos têm em comum. Em nenhum deles o problema foi obter o certificado. O problema foi entregá-lo corretamente ao servidor e fazer o servidor usá-lo:

    • No Nginx, o certificado estava no disco mas não na memória.
    • No Apache, o certificado estava certo mas a cadeia estava incompleta ou mal ordenada.
    • No Tomcat, o certificado precisava estar no formato e na estrutura que o Java exige.

    Multiplique isso por uma infraestrutura real, com dezenas de servidores heterogêneos — alguns Nginx, alguns Apache de versões diferentes, alguns Tomcat — e por um ciclo de renovação que, com a ballot SC-081, vai chegar a oito renovações por ano por certificado até 2029. Gestão manual, servidor por servidor, com um procedimento diferente para cada um, não escala.

    O que isso exige de uma estratégia de automação

    Automatizar a emissão resolve metade do problema. A outra metade — a que realmente derruba sites — é a implantação. Uma estratégia de deploy de certificados que dá conta desses casos precisa:

    Conhecer as particularidades de cada servidor. Escrever fullchain para Nginx, concatenar corretamente para Apache 2.4.8+, reconstruir keystore com formato e alias corretos para Tomcat. Um "deploy genérico" que trata todos os servidores igual reproduz exatamente os bugs acima.

    Recarregar o serviço da forma certa. Não basta copiar o arquivo. Cada servidor tem seu mecanismo — e no caso do Nginx, saber quando um reload não é suficiente e um restart é necessário.

    Verificar o que está sendo servido, não o que está no disco. A validação precisa abrir uma conexão TLS e confirmar que o certificado apresentado é o novo e que a cadeia está completa — a única forma de pegar o gap "renovou mas não recarregou".

    Descobrir onde os certificados realmente estão. Você não pode automatizar o deploy em servidores que não sabe que existem. Descoberta contínua é o pré-requisito de qualquer automação confiável.

    O objetivo final é simples de enunciar e difícil de fazer à mão: que a renovação de um certificado chegue, corretamente formatada e efetivamente carregada, a cada ponto que o consome — seja um Nginx, um Apache ou um Tomcat — sem intervenção manual e sem a descoberta tardia de que o site está fora do ar.

    Perguntas frequentes

    Por que meu certificado renovou mas o navegador ainda mostra o antigo (ou como expirado)?

    No Nginx e em vários outros servidores, o certificado é carregado em memória no momento do parse da configuração. Substituir o arquivo no disco não troca o que os workers ativos apresentam — é preciso um reload (ou, em alguns casos, um restart completo) para o servidor carregar o material novo. Se o reload não aconteceu ou falhou, o servidor continua servindo o certificado antigo mesmo com o arquivo novo no disco.

    Por que o site funciona no meu navegador mas dá erro de certificado no celular?

    Quase sempre é cadeia incompleta: o certificado intermediário não está sendo servido. Navegadores desktop frequentemente cacheiam intermediários de visitas anteriores e "escondem" o problema, enquanto navegadores mobile não cacheiam e falham imediatamente. A correção é garantir que o servidor sirva o leaf seguido dos intermediários, na ordem correta.

    Por que renovar certificado no Tomcat é mais complicado que no Nginx ou Apache?

    Porque o Tomcat usa keystores (JKS ou PKCS12) em vez de arquivos PEM soltos. Renovar exige reconstruir o keystore com o formato correto, incluir a cadeia dentro dele e usar o alias correto, além de reiniciar o serviço. São mais passos e mais pontos de falha do que a simples substituição de arquivo dos outros servidores.

    Automação de emissão (ACME/certbot) não resolve tudo isso sozinha?

    Não. Clientes ACME resolvem muito bem a emissão e a renovação, mas o deploy correto em cada tipo de servidor — formato, cadeia, reload adequado e verificação do que está efetivamente sendo servido — é uma etapa separada. É justamente nessa etapa de implantação, não na de emissão, que a maioria dos incidentes de certificado acontece.

    Veja a documentação técnica

    Guias de integração, API e automação em docs.pkiless.com.

    Abrir docs

    Automatize o lifecycle dos seus certificados

    Descoberta, renovação e deploy automáticos — pronto para a validade de 47 dias.

    Testar PKILESS grátis