Falha do Discourse ao renovar certificado

Continuando a conversa a partir daqui:

A primeira vez que recebi um lembrete da Redsift de que meus certificados iriam expirar em uma semana. Normalmente, o Discourse renova os certificados com bastante antecedência. Desta vez não, antes de começar a reconstruir (o que supostamente resolve o problema), @Falco, há algo que você gostaria que eu verificasse e postasse aqui para ajudar a chegar à raiz do motivo pelo qual os certificados não foram renovados?

A raiz do certificado é ISRGX1 e aqui estão as informações do certificado que está expirando:

Nome Comum (CN) E6
Organização (O) Let’s Encrypt
Unidade Organizacional (OU) <Não faz parte do certificado>
Emitido em Quarta-feira, 16 de julho de 2025 às 19:36:45
Expira em Terça-feira, 14 de outubro de 2025 às 19:36:44

A compilação atual é 3.6.0.beta1-dev (7ee52c8f85)

Houve um período em que o endpoint que o Let’s Encrypt precisava foi redirecionado. Isso foi corrigido se você reconstruir.

5 curtidas

Quanto tempo depois de atualizar o certificado deve ser renovado?

Se a memória não me falha, os certificados são válidos por 3 meses, e eles agora tentarão renovar automaticamente antes disso.

1 curtida

Sim, eu sei como funciona.

Mas já se passou mais de um dia desde que atualizei o software do fórum e o certificado ainda não parece ter sido atualizado. Faltam 5 dias para expirar, então ele realmente precisa ser renovado em breve.

Estou no branch estável do Discourse, se isso fizer alguma diferença. É possível que a correção do endpoint não tenha sido retroportada?

Para mim, o certificado foi atualizado imediatamente após a reconstrução.

Você reconstruiu pela web ou pela linha de comando?

1 curtida

Sim, a explicação estava aqui:

1 curtida

Meu fórum finalmente atualizou seu certificado depois que fiz uma reconstrução na linha de comando.

3 curtidas

Tivemos a mesma experiência de SSL não renovado.

Seria ótimo se alguém pudesse verificar se o web.ssl.template está se comportando corretamente no discourse-docker, pareceu-me que a porta 80 não estava servindo nenhum URL de /.well-known/ usado pelo Let’s Encrypt, todos os URLs estavam redirecionando para SSL, incluindo arquivos de teste que coloquei manualmente em /var/www/discourse/public/.well-known/. Tive que editar /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf diretamente dentro do contêiner do aplicativo.

Talvez isso tenha começado após o commit ae4887a do discourse-docker?

1 curtida

Houve outro erro na rota mais conhecida em memória recente.

Quando foi a última vez que você fez uma reconstrução?

1 curtida

O mesmo aqui. Não recebi um aviso sobre a expiração do certificado. Entrar no servidor e iniciar uma reconstrução /var/discourse % ./launcher rebuild resolveu o problema.

2 curtidas

Em meus testes em uma instalação vanilla do nginx (1.18.0, mas acho que é o mesmo para 1.26.3), uma linha de configuração do nginx return 301 https://thehostname$request_uri; fora de um location substitui completamente qualquer bloco location anterior, em vez de ser um catch-all. Acredito que /.well-known/ simplesmente não é servido na porta 80, a menos que o redirecionamento 301 seja especificamente para outro location, como / no final do bloco server. Poderia ser o mesmo problema que este post do stackoverflow?

Fico feliz que o rebuild funcione, mas como o certificado já havia sido renovado para mim, não pude confirmar se um rebuild permitiria que os servidores de validação do Let’s Encrypt chegassem lá se um certificado tivesse expirado. Talvez um rebuild inicie a renovação do certificado antes que essa linha de template esteja em vigor ou algo semelhante, em vez de corrigir os templates, mas não consigo confirmar se é por isso que o rebuild faz a renovação funcionar.

Se você acha que isso é um Discourse, então talvez você deva responder no commit do github ou abrir um novo relatório grande.

1 curtida

Posso confirmar que a renovação do Letsencrypt falha. Tenho executado uma instalação Discourse auto-hospedada por anos, e muito estranhamente a renovação falhou para mim duas vezes seguidas nos últimos meses. A segunda vez foi hoje de manhã, e então comecei a investigar.

Eu rastreei até os seguintes dois commits:

E a linha relevante vinculada:

Existem dois problemas, eu acho.

Primeiro, return 301 https://${DISCOURSE_HOSTNAME}$request_uri; se transforma em return 301 https://<MEU NOME DO SERVIDOR> sem um $request_uri no final. Eu verifiquei na minha instalação auto-hospedada, e também na instalação auto-hospedada de um amigo que foi configurada na última semana. Eu não entendo como o template do Discourse funciona, então não sei por que ele é descartado.

Segundo, como @lessLost mencionou, o redirecionamento 301 está fora do bloco location. Eu acredito que um redirecionamento no nível do servidor anula todos os blocos location. O LetsEncrypt usa http para renovações. No entanto, qualquer tentativa de curl -I http://SEU_DOMINIO/.well-known/acme-challenge/test retornará um 301 para https, em vez de um 404 (que é o comportamento esperado; queremos um 404, não um 301).

Eu corrigi isso manualmente na minha instalação auto-hospedada, mas espero que qualquer atualização substitua minhas alterações. Infelizmente, eu não entendo os templates o suficiente para enviar um pull request @pfaffman — ou eu faria isso também.

Editado para adicionar:

Eu acredito que isso está incorreto —

Tenho certeza de que o LetsEncrypt usa http por padrão (por razões óbvias, se o certificado estiver expirado, ele não pode ser renovado!) Mas colocar o 301 no nível do bloco server força todas as requisições a redirecionar para https, o que é inconsistente com esta estratégia de renovação.

1 curtida

Quando você reconstruiu pela última vez?

Esta manhã, cerca de 10 minutos depois de eu acordar, visitei meu fórum e percebi que o certificado havia expirado novamente. (Reconstruir foi o que renovou da última vez que expirou para mim — há cerca de 3 meses?)

Acho que eles fizeram alterações desde então que corrigiram esse problema, mas como leva 3 meses para descobrir, o júri ainda não decidiu. Você pode definir um lembrete algumas semanas antes de o certificado atual expirar.

1 curtida

Isso não é verdade.

  1. Os links que anexei no comentário anterior eram de um git blame. Aqui está a versão mais recente do arquivo (linha relevante vinculada): discourse_docker/templates/web.ssl.template.yml at 247c71a1e45d32b0b814a8e9d5fdaa4faaf727b9 · discourse/discourse_docker · GitHub
  2. A nova instalação do site do meu amigo foi de uma semana atrás. A linha 37 do modelo acima diz: return 301 https://${DISCOURSE_HOSTNAME}$request_uri; mas no contêiner do Discourse Docker, tanto o dela (quanto o meu) /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf diz return 301 https://<seu_site_discourse>; Note como $request_uri é removido. Algo está fazendo com que isso desapareça! (Eu não sei o quê).
  3. Eu fiz uma renovação forçada simulada esta manhã como parte da minha investigação. Falhou. Eu então mudei /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf. Teve sucesso!

Na verdade, tudo bem; eu apenas editarei manualmente 20-redirect-http-to-https.conf toda vez que eu atualizar o Discourse. Para aqueles que encontrarem este comentário, o comando a ser executado é:

cat > /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf << 'EOF'
server {
  listen 80;
  listen [::]:80;

  location ~ /.well-known {
    root /var/www/discourse/public;
    allow all;
  }

  location / {
    return 301 https://<SEU_ENDERECO_DO_FORUM>$request_uri;
  }
}
EOF

Eu não tenho total certeza do que está causando essa falha, mas sei que modificar o conf acima resolve. Mas eu também modifiquei as notificações para que as renovações do letsencrypt não falhem silenciosamente — para que eu possa ter algum aviso prévio. Só pensei que você gostaria de saber!

4 curtidas

Obrigado pelo relatório, acho que isso é legítimo.

(para sua informação @featheredtoast)

6 curtidas