Há algum tempo – não está claro há quanto tempo, mas pelo menos vários meses – as renovações do Let’s Encrypt começaram a falhar no meu fórum Discourse, depois de funcionarem bem por anos. Quando notei isso inicialmente há alguns dias, o certificado havia expirado em agosto de 2021. Depois de tentar algumas renovações manuais e reinicializações do nginx, descobri que o certificado foi atualizado para expirar apenas alguns dias atrás. Ainda não é um certificado atual, obviamente. Executar manualmente o acme.sh para forçar uma renovação (dentro do contêiner do Discourse) está gerando este erro (onde [site] é o endereço do meu site, é claro):
[site]:Verify error:Fetching http://[site]/.well-known/acme-challenge/[long alpha challenge string]: Error getting validation data
Devo notar que o site exige login para todo o acesso do usuário, mas isso não tem sido um problema para as renovações de certificados SSL durante os anos de operação anterior.
Alguma ideia? Muito obrigado!
ATUALIZAÇÃO: Testar a verificação usando wget retorna um 404. No entanto, não sei onde esses dados são configurados no nginx para o Discourse em um contêiner e como eles se relacionam com o nginx relacionado que faz proxy fora do contêiner.
Oi. Isso não deveria ter relação, pois esse problema faria com que os certificados fossem rejeitados pelo navegador com erros diferentes, e não erros de expiração como no meu caso. Parece que o Let’s Encrypt, de repente, não consegue autenticar com o Discourse para entregar novos certificados. Obrigado.
Oi. Estes não parecem se aplicar. Estou vendo um erro 404, não os outros erros, as compilações foram atualizadas o tempo todo, e aquele template do github é de fato a versão já instalada na minha instalação. Obrigado!
Executando manualmente o cron job (em contêiner) para renovação de certificado, a falha é sempre a mesma. A tentativa de obter:\n\nhttp://[site]/.well-known/acme-challenge/[challenge-string]\n\nfalha com “Erro ao obter dados de validação.”
Por não estar familiarizado com o processo, poderia ser que ele esteja esperando que o contêiner esteja em um estado que não é o caso quando se executa esse script sozinho? Por exemplo, talvez ele esteja esperando que outro trabalho cron ocorra primeiro, o que prepara o nginx para permitir o acesso a tal URL.
Você tentou fazer uma reconstrução? (O que tentará obter um novo certificado no processo.)
Você menciona que está hospedado localmente. Você consegue acessar a instância de fora da sua rede usando o nome de domínio?
Olá, sim várias reconstruções. Nenhuma mudança. Eu uso o Let’s Encrypt em vários sites que não são do Discourse e todos eles são renovados sem problemas. Sim, posso acessar de um site externo e testei usando wget, o resultado é 404. Pergunta: Exatamente onde fica a árvore html do nginx neste caso, a parte que conteria (ou deveria conter) o diretório .well-known? Não consegui encontrá-lo. Obrigado.
Não encontrei um cron job, apenas um script de runlevel em /etc/runit/1.d/letsencrypt. Parece que esse script inicia uma nova instância do nginx com uma configuração que inclui isto:
Acho que isso significa que o caminho acabaria sendo /var/www/discourse/public/acme-challenge, embora possa ser criado antes do desafio e removido depois.
Se esse é o script que você tentou executar manualmente, você parou o nginx primeiro? A instância que o script tenta iniciar tentará escutar na porta 80, então suspeito que isso falharia se o nginx já estivesse em execução para o Discourse.
Acho que posso ter encontrado o problema. Mas não sei como consertá-lo. Parece que todas as tentativas de acessar o fórum na porta 80 https estão sendo (como esperado) redirecionadas para a porta 443 https. Certo. Mas isso significa que, quando o Let’s Encrypt tenta validar para a renovação, ele falha, porque o certificado atual expirou. Posso ver o redirecionamento com wget. Então, a pergunta é: como desabilito o redirecionamento temporariamente para que o Let’s Encrypt possa validar e me fornecer um novo certificado não expirado? Uma complicação adicional possível é que o redirecionamento é um 301 permanente. Obrigado.
Este redirecionamento está em /etc/nginx/conf.d/discourse.conf e não será usado quando o nginx for parado e, em seguida, iniciado com a configuração mencionada em minha postagem anterior.
Receio não estar muito familiarizado com o funcionamento da atualização automática, portanto, não tenho certeza de qual seria o método apropriado para renovar enquanto o contêiner estiver em execução. Em teoria, apenas parar e iniciar o contêiner deveria resultar na renovação, mas como você disse que uma reconstrução não resolveu, isso provavelmente também não resolverá.
O acme.sh tem opções como --renew-all, mas não tenho certeza de quais outras opções são necessárias para que ele faça a coisa certa aqui. O seguinte pode ser tudo o que você precisa, mas não posso garantir.
E, de fato, isso permite que o Let’s Encrypt acesse sem o redirecionamento, mas aparentemente o arquivo que ele está procurando não existe, resultando, em última análise, na mesma falha de verificação.
Estou agora usando isso para tentar obter o certificado com sucesso. Parece que o token de validação ESTÁ sendo recuperado pelo curl, mas o acme.sh AINDA está declarando uma falha de validação toda vez! Então, ainda está indisponível.
Com muitos clientes ACME (como acme.sh) quando o nginx é especificado como método de autenticação, o arquivo do desafio http-01 é criado em um diretório específico com base em uma exceção/redirecionamento na configuração do servidor nginx, em vez de diretamente na estrutura de diretórios .well-known/acme-challenge no diretório raiz da web. Frequentemente, esse redirecionamento existe apenas temporariamente durante a verificação do desafio, assim como os próprios arquivos de desafio.
Daí:
Uma consideração sábia. Um script de renovação escrito corretamente deve tornar desnecessário parar o nginx. Normalmente, o nginx é usado para servir os arquivos de desafio e, em seguida, algo como nginx -s reload é usado para recarregar graciosamente o servidor web/proxy assim que o novo certificado for adquirido.
Nossa implementação do desafio HTTP-01 segue redirecionamentos, até 10 redirecionamentos de profundidade. Ele aceita apenas redirecionamentos para “http:” ou “https:”, e apenas para as portas 80 ou 443. Ele não aceita redirecionamentos para endereços IP. Quando redirecionado para uma URL HTTPS, ele não valida certificados (já que este desafio tem como objetivo inicializar certificados válidos, ele pode encontrar certificados autoassinados ou expirados ao longo do caminho).
Normalmente, quando vemos problemas como este, um destes é geralmente o culpado:
Um firewall não está permitindo tráfego para o servidor web/proxy que está servindo os arquivos de desafio.
Um roteador/proxy está mapeado/configurado incorretamente de tal forma que a solicitação de verificação de desafio do Boulder (o servidor CA do Let’s Encrypt) tenta recuperar os arquivos de um servidor web ou diretório incorreto.
Algum tipo de reescrita/redirecionamento (por exemplo, arquivos .htaccess no Apache) está interferindo na capacidade do servidor web/proxy de servir os arquivos de desafio da localização correta.
Uso de portas não padrão, geralmente com mapeamento incorreto.
O contêiner que executa o cliente ACME está criando os arquivos de desafio em um local onde o servidor web/proxy (por exemplo, nginx) não os serve. Quando o docker está envolvido, este é quase sempre o problema.
Olá. Portanto, desses vários itens que você listou, vários claramente não se aplicam ao meu caso. Não é um problema de firewall - posso acessar manualmente o token com wget ou curl de todos os 1) dentro do aplicativo docker discourse, 2) de fora do contêiner docker no sistema host e 3) um sistema relacionado.
Para esses casos manuais, EU recebo o conteúdo do token do local esperado, assumindo que --ignore ou -k é especificado para passar pelo certificado expirado quando o Discourse redireciona para https automaticamente.
Não alterei nenhum aspecto da configuração do nginx criada pelo Discourse, nem dentro nem fora do contêiner docker do Discourse. Não executo nenhuma cópia do nginx e o Apache vive em portas completamente diferentes apenas para uso local. Notando que tudo isso estava funcionando bem por mais de dois anos, com renovações de certificado rotineiras e sem outras alterações no aplicativo - é uma caixa muito estável.
Sem portas incomuns.
Como posso obter o conteúdo do token manualmente, não vejo como locais errados poderiam estar envolvidos. EXCETO…
Eu não estava parando manualmente o nginx para meus testes. Agora fiz isso, e não houve diferença significativa - os mesmos erros do acme.sh (atualmente erro 56 novamente). Quando o nginx é parado de dentro do contêiner, vejo uma instância runsv nginx no host, mas ela não tem processos de worker ou cache. Quando reinicio o nginx no contêiner, os processos de worker e cache reaparecem no host junto com o runsv nginx que permaneceu. Os comandos sv start/stop nginx dentro do contêiner dão as confirmações esperadas dessas ações.
Mas há algo mais mencionado acima que pode ser motivo de preocupação. E eu não entendo por que isso seria um problema repentino, dado o tempo que as coisas estavam funcionando até agora.
O endereço IP estático do fórum que é usado de fora de minhas redes locais não é utilizável por essa máquina para se conectar aos próprios serviços dessa máquina, devido a complexidades na forma como os IPs estáticos são fornecidos pelo ISP. Eu rotineiramente usei entradas em /etc/hosts para fornecer endereços IP de rede local para esses nomes. Portanto, quando testo com curl na mesma máquina (dentro ou fora do contêiner, ambos têm a adição em /etc/hosts para o fórum), o teste usa um endereço IP diferente (e local) do que seria usado por um site externo que o consulta via DNS. Há alguma maneira de isso ser relevante? Obrigado.