Discourse + Let's Encrypt avec plusieurs noms d'hôte

Lors de la migration (via une sauvegarde) d’un Discourse d’un nom d’hôte à un autre, un administrateur peut souhaiter conserver l’ancien nom d’hôte tout en configurant le serveur web pour réécrire les requêtes afin d’utiliser le nouveau nom canonique, par exemple :

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

Malheureusement, cela n’est pas aussi simple que de modifier simplement l’enregistrement CNAME ou A dans le DNS ; le client navigateur générera une erreur ou un avertissement car le nom d’hôte ne correspond pas au certificat généré par l’installation de Discourse via Let’s Encrypt.

Sur une installation manuelle d’un serveur web, j’utiliserais l’outil certbot pour générer un certificat avec plusieurs noms qui lui sont attribués. Cependant, la configuration de Discourse ne transmet à Let’s Encrypt que le nom d’hôte de Discourse (et uniquement celui-ci), et je ne vois aucune notion d’alias dans la configuration de Discourse.

Quelqu’un a-t-il mis en place une telle configuration, ou a-t-il une idée de la meilleure façon de le faire ? J’imagine que cela impliquera quelques modifications des modèles SSL et Let’s Encrypt.

Ce n’est pas spécifique à Discourse, mais lorsque je dois rediriger vers HTTPS, je redirige simplement tout. Cela signifie avoir un serveur qui effectue la redirection de l’ancienne adresse vers la nouvelle. Certaines options d’hébergement s’en chargent en arrière-plan, parfois appelées service de « redirection de domaine » ou de « transfert ».

Je ne m’en soucie même plus, car c’est tellement pénible à chaque fois que j’ai essayé autre chose. :thinking:

Discourse ne répondra qu’à un seul nom d’hôte. Si vous souhaitez plusieurs noms d’hôte — et que votre cas d’usage, qui consiste à prendre en charge l’ancien nom d’hôte, est le plus courant —, vous devrez alors rediriger l’un vers l’autre.

Je recommande de le faire en dehors de Discourse. Il suffit de créer une configuration nginx qui aura son propre certificat, un server_name pour l’ancien nom d’hôte, et qui redirigera tout vers le nouveau nom d’hôte.

En fait, si vous utilisez une installation basée sur Docker avec une seule instance par serveur, elle répondra correctement à n’importe quel nombre d’entrées DNS (nginx écoute sur les ports 80 et 443 pour tous les noms d’hôte) et réécrira correctement l’URL vers le nouveau nom d’hôte canonique. Cette partie fonctionne bien et sans problème. (Les personnes souhaitant tester cela peuvent ajouter un faux nom de domaine dans le fichier localhost de leur machine et le pointer vers l’adresse IP de leur site Discourse préféré.)

Le seul problème que je rencontre est l’avertissement SSL, car la réponse de réécriture de nginx provient de https://old.example.org/foo et envoie une redirection HTTP 302 vers la nouvelle URL.

Je préférerais ne pas avoir à maintenir un serveur web séparé juste pour appliquer une règle de réécriture, si possible. :slight_smile:

Ce n’est pas nécessaire, il vous suffit d’ajouter une section server supplémentaire dans votre configuration.

Vous devriez peut-être consulter Set up Let’s Encrypt with multiple domains / redirects

Mise à jour : Configuration réussie du nom de domaine secondaire sur l’installation autonome, et émission d’un certificat Let’s Encrypt pour gérer à la fois les anciens et les nouveaux noms.

Prérequis : Je n’ai pas encore modifié les enregistrements DNS pour rediriger les utilisateurs vers le nouveau site ; je voulais m’assurer que tout fonctionnerait à l’avance. J’ai donc utilisé une entrée localhost sur ma machine de test. Cela signifie que je ne pouvais pas effectuer une vérification Let’s Encrypt normale, et j’ai dû utiliser la méthode « DNS » d’acme.sh, généralement déconseillée car elle ne permet pas le renouvellement automatique. Cela ne me pose pas de problème car je passerai au nouveau nom dans les 30 jours suivant l’émission du certificat « initial » (à deux noms).

  1. Dans mon fichier web_only.yml (vous utilisez peut-être app.yml), sous la section hooks: et avant les plugins, ajoutez ce qui suit :
  after_ssl:
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d second-domain.com --keylength"
  1. Dans DNS, créez un enregistrement TXT factice/temporaire pour _acme-challenge.old.example.org avec un TTL de 5 minutes (vous pouvez probablement le définir plus court) et laissez-le se propager afin de modifier rapidement la clé de vérification acme.sh (Let’s Encrypt).

  2. Arrêtez le site et lancez une validation de débogage (test) pour que le système prenne conscience du TTL court de la nouvelle entrée :

./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. Exécutez la requête cette fois sans le paramètre de débogage. Cela vous affichera un avertissement avec la valeur à utiliser dans DNS pour l’entrée créée à l’étape 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. Mettez à jour DNS, puis attendez 5 minutes. Oui, vous devez attendre tout ce temps pour éviter les limitations de Let’s Encrypt.

  2. Exécutez une version similaire de la dernière commande mais en mode 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. Vous devriez obtenir une confirmation. Exécutez la commande suivante pour nettoyer et installer le nouveau certificat :
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. Dernière étape maintenant que vous avez quitté le launcher :
rm -rf /var/discourse/shared/standalone/ssl
rm -rf /var/discourse/shared/standalone/letsencrypt
./launcher rebuild app

Une fois le site de nouveau en ligne, il devrait fonctionner avec le nouveau certificat. Vous devrez peut-être vider les certificats stockés dans votre navigateur, ce que je vous laisse à vous-même et à votre moteur de recherche préféré.

Merci à ceux qui m’ont orienté dans la bonne direction !

Ceci est une application parfaite pour une règle Cloudflare : aucune configuration serveur n’est requise. Il suffit d’appliquer les mêmes paramètres d’URL au nouveau domaine.

Le nuage orange devra être activé pour l’ancien nom de domaine.

Oui, une situation de proxy inverse comme Cloudflare (ou, je suppose, votre propre proxy inverse de choix devant votre site Discourse) pourrait contourner le problème en implémentant les règles de réécriture « un niveau plus haut ». Dans ce cas, Cloudflare n’était pas une option pour des raisons de sécurité et morales. :slight_smile:

(Voir ci-dessus pour une solution autonome.)