Discourse + Let's Encrypt com múltiplos nomes de domínio

Ao migrar (via backup) um Discourse de um hostname para outro, um administrador pode querer manter o antigo hostname, mas fazer com que o servidor web reescreva as solicitações para usar o novo nome canônico, por exemplo:

https://old.example.org/t/my-great-topic/12345 :arrow_heading_down:
https://new.example.org/t/my-great-topic/12345

Infelizmente, isso não é tão simples quanto apenas alterar o registro CNAME ou A no DNS; o cliente do navegador gerará um erro/aviso porque o hostname não corresponde ao certificado gerado pela instalação do Discourse via Let’s Encrypt.

Em uma instalação manual de um servidor web, eu usaria a utilidade certbot para gerar um certificado com múltiplos nomes atribuídos a ele. No entanto, a configuração do Discourse passa apenas o hostname do Discourse para o Let’s Encrypt, e não há nenhum conceito visível na configuração do Discourse para aliases.

Alguém configurou tal arranjo ou tem uma ideia de como melhor alcançá-lo? Imagino que envolverá alguma modificação nos templates de SSL e Let’s Encrypt.

Não é específico do Discourse, mas quando preciso redirecionar via HTTPS, redireciono tudo. Isso significa ter um servidor fazendo o redirecionamento do endereço antigo para o novo. Algumas opções de hospedagem cuidam disso nos bastidores, às vezes chamadas de serviço de “redirecionamento de domínio” ou “encaminhamento”.

Eu nem penso mais nisso, porque é tão trabalhoso cada vez que tento qualquer outra coisa. :thinking:

O Discourse responderá apenas a um nome de host. Se você quiser mais de um nome de host — e seu caso de uso, que é dar suporte ao nome de host anterior, for o mais comum —, então você precisará redirecionar um para o outro.

Recomendo fazer isso fora do Discourse. Basta criar uma configuração do nginx que tenha seu próprio certificado, tenha um server_name para o nome de host antigo e redirecione tudo para o novo nome de host.

Na verdade, se você estiver usando uma instalação baseada em Docker com uma única instância por servidor, ele responderá normalmente a qualquer número de entradas DNS (o nginx está escutando nas portas 80 e 443 para todos os nomes de host) e reescreverá corretamente a URL para o novo nome de host canônico sem problemas. Essa parte está funcionando perfeitamente e sem complicações. (Quem estiver interessado em testar isso pode adicionar um nome de domínio fictício ao arquivo localhost da sua máquina e apontá-lo para o endereço IP de seu site Discourse favorito.)

O único problema que estou enfrentando é o aviso de SSL, pois a resposta de reescrita do nginx vem de https://old.example.org/foo e envia um redirecionamento HTTP 302 para a nova URL.

Preferiria não ter que manter um servidor web separado apenas para aplicar uma regra de reescrita, se possível. :slight_smile:

Você não precisa, basta adicionar uma seção server extra na sua configuração.

Talvez dê uma olhada em Set up Let’s Encrypt with multiple domains / redirects

Atualização: Domínio secundário configurado com sucesso na instalação standalone e certificado Let’s Encrypt emitido para lidar com os nomes antigo e novo.

Pré-requisito: Ainda não alterei o DNS para redirecionar os usuários ao novo site; queria garantir que tudo funcionasse antes. Por isso, usei uma entrada localhost na minha máquina de testes. Isso significa que não pude fazer a verificação normal do Let’s Encrypt e precisei usar o método “DNS” do acme.sh, que geralmente não é recomendado porque não permite renovação automática. Isso não é um problema para mim, pois farei a troca dentro do prazo de 30 dias do certificado “inicial” (emitido recentemente para os dois nomes).

  1. No meu arquivo web_only.yml (você pode estar usando app.yml), na seção hooks:, antes dos plugins, adicionei o seguinte:
  after_ssl:
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d second-domain.com --keylength"
  1. No DNS, configurei um registro TXT falso/temporário para _acme-challenge.old.example.org com TTL de 5 minutos (você provavelmente poderia definir um valor menor) e esperei a propagação para fazer a alteração rapidamente com a chave de verificação do acme.sh (Let’s Encrypt).

  2. Pare o site e execute uma validação de depuração (teste) para que o sistema reconheça o TTL curto da nova entrada:

./launcher enter app
sv stop nginx
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf
LE_WORKING_DIR=/shared/letsencrypt DEBUG=1 /shared/letsencrypt/acme.sh --issue -d new.example.org -d old.example.org -k 4096 -w /var/www/discourse/public --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force
  1. Execute a solicitação de verdade desta vez, sem a configuração de depuração. Isso gerará um aviso com o valor a ser usado no DNS para a entrada criada na etapa 2:
LE_WORKING_DIR=/shared/letsencrypt /shared/letsencrypt/acme.sh --issue -d new.example.org -d old.example.org -k 4096 -w /var/www/discourse/public --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force
  1. Atualize o DNS e aguarde 5 minutos. Sim, você deve aguardar o tempo total para não esbarrar nas limitações do Let’s Encrypt.

  2. Execute uma versão semelhante ao último comando, mas no modo renew:

LE_WORKING_DIR=/shared/letsencrypt /shared/letsencrypt/acme.sh --issue -d new.example.org -d old.example.org -k 4096 -w /var/www/discourse/public --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force --renew
  1. Você deverá receber uma confirmação. Execute o seguinte para limpar as configurações e colocar o novo certificado no lugar:
LE_WORKING_DIR=/shared/letsencrypt /shared/letsencrypt/acme.sh --installcert -d new.example.org -d old.example.org --fullchainpath /shared/ssl/new.example.org.cer --keypath /shared/ssl/new.example.org.key --reloadcmd "sv reload nginx"
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop
exit
  1. Última etapa, agora que você saiu do launcher:
rm -rf /var/discourse/shared/standalone/ssl
rm -rf /var/discourse/shared/standalone/letsencrypt
./launcher rebuild app

Assim que o site voltar, ele deverá estar rodando com o novo certificado. Talvez seja necessário limpar os certificados armazenados no seu navegador, o que fica como exercício para o leitor e seu mecanismo de busca favorito.

Obrigado às pessoas que me indicaram o caminho certo!

Esta é uma aplicação perfeita para uma regra do Cloudflare — configuração zero no servidor. Basta enviar os mesmos parâmetros de URL para o novo domínio.

A nuvem laranja precisará estar ativada para o domínio antigo.

Sim, uma situação de proxy reverso como o Cloudflare (ou, supostamente, seu próprio proxy reverso de escolha na frente do seu site Discourse) poderia contornar isso implementando as regras de reescrita “um nível acima”. Neste caso, o Cloudflare não era uma opção por motivos de segurança e éticos. :slight_smile:

(Veja acima para a solução independente.)