Configurer Let's Encrypt avec plusieurs domaines / redirections

NOTE: @pfaffman says: This page needs to be cleaned up. There is now a new ENV setting that will let you add more hostnames. In your app.yml under your DISCOURSE_HOSTNAME line (it can go many places but that one makes sense), add

 DISCOURSE_HOSTNAME_ALIASES: domain.com,other.domain.com

and early reports suggest that you’ll get valid certs for those domains and that accessing https://domain.com will properly redirect you to your DISCOURSE_HOSTNAME without a certificate error.

If you do that and it works for you, you might add another “me too!” post to the bottom. If you feel comfortable, you could also edit this first post with the instructions that you think would be most helpful.


This is to address the problem where you get certificate errors with any redirects or CNAME DNS entries which point to your actual installed Discourse (sub)domain.

If you do not have https configured already (you do if you have done a standard install recently) see Setting up Let’s Encrypt as your first step.

Legacy Method

The method below no longer reliably works as of August 2025

There are three patterns that need to be replaced. Enter your (sub)domain (and any additional subdomains preceded by -d ) and then add the following to your app.yml hooks section (towards the end of the file):

2025-04-23 @pfaffman changed the code because there’s a 3rd place it needs to be changed

  after_ssl:
    - replace:
        filename: /etc/runit/1.d/letsencrypt
        from: /-d =domain1= /
        to: "-d =domain1= -d =domain2= "
        global: true

This will allow you to have HTTPS configured for a second domain that will redirect to the correct one without certificate issues.

If you need to add multiple extra domains, you can enter something like this in the domain2 field: www.bananas.com -d forum.bananas.com

For example, if you want people who visit https://forum.example.com to be redirected to your forum at https://community.example.com without a certificate error, this is all you need.

47 « J'aime »

Merci, cela fonctionne pour rediriger « www.example.com » vers « community.example.com » ?
Ou comment puis-je le faire ?
J’ai des problèmes avec mon domaine www.example.com, j’ai configuré le DNS pour rediriger vers community.example.com mais cela ne fonctionne pas sur Firefox ou Chrome.

2 « J'aime »

Il existe un outil de vérification des redirections pour vérifier vos redirections.

5 « J'aime »

J’ai un peu de mal avec ça. OK, beaucoup.

J’ai décidé d’expérimenter en ajoutant un CDN à l’un de mes sites.

Après avoir lu la documentation, j’ai réalisé qu’il était préférable pour mon site de passer d’un domaine apex actuel à un sous-domaine afin de répondre aux critères recommandés par Fastly (et aux conseils généraux de le faire).

Alors j’ai pensé : “meh, ça va être un jeu d’enfant, je l’ai déjà fait…” oh oui ?! :sweat_smile:
Le site en question est https://starzen.space.

Je l’ai déplacé ce week-end vers https://www.starzen.space en utilisant le guide ici

Tout s’est bien passé, MAIS bien sûr, je dois encore tenir compte du petit nombre d’utilisateurs que j’ai déjà acquis sur ce site, j’ai donc voulu ajouter une redirection.

D’après ma compréhension, j’ai alors aussi besoin du lien original délivré avec un certificat, donc en suivant ce guide (qui était beaucoup plus impliqué auparavant ?), j’ai ajouté ceci à app.yml :

hooks:
  after_ssl:
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d starzen.space --keylength"
    - replace:
        filename: "/etc/nginx/conf.d/discourse.conf"
        from: /return 301 https.+/
        to: |
          return 301 https://$host$request_uri;
  after_web_config:
    - replace:
        filename: /etc/nginx/nginx.conf
        from: /sendfile.+on;/
        to: |
          server_names_hash_bucket_size 64;
          sendfile on;
    - file:
        path: /etc/nginx/conf.d/discourse_redirect_1.conf
        contents: |
          server {
            listen 80;
            listen 443 ssl;
            server_name starzen.space;
            return 301 $scheme://www.starzen.space$request_uri;
          }

Lors d’une reconstruction, tout semble bien se passer.

Cependant, si j’essaie d’accéder à https://starzen.space via un navigateur, j’obtiens :

Et si je fais un curl :

blah discourse % curl https://starzen.space
curl: (60) SSL: no alternative certificate subject name matches target host name 'starzen.space'
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Je suis à peu près sûr que c’est le certificat qui est en cause, car si j’exécute la même commande en mode non sécurisé, j’obtiens :

blah discourse % curl -k https://starzen.space

301 Moved Permanently
nginx/1.21.6

ce qui, je crois, est ce que je veux.

Je pense que le script modifié est correct, voici ce que j’ai :

root@starship-enterprise:/etc/runit/1.d# cat letsencrypt 
#!/bin/bash
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf

issue_cert() {
  LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh --issue $2 -d www.starzen.space -d starzen.space --keylength $1 -w /var/www/discourse/public
}

cert_exists() {
  [[ "$(cd /shared/letsencrypt/www.starzen.space$1 && openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer | grep "OK")"]]
}

########################################################
# RSA cert
########################################################
issue_cert "4096"

if ! cert_exists ""; then
  # Try to issue the cert again if something goes wrong
  issue_cert "4096" "--force"
fi

<SNIP>

J’ai même exécuté ceci depuis la ligne de commande dans le conteneur, après avoir déplacé TOUS les fichiers de certificat du répertoire cible vers un répertoire de sauvegarde afin que la bonne commande soit exécutée pour le double domaine :

root@starship-enterprise:/etc/runit/1.d# ./letsencrypt 
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
[Sun 25 Sep 2022 05:50:04 PM UTC] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Sun 25 Sep 2022 05:50:04 PM UTC] Creating domain key
[Sun 25 Sep 2022 05:50:05 PM UTC] The domain key is here: /shared/letsencrypt/www.starzen.space/www.starzen.space.key
[Sun 25 Sep 2022 05:50:05 PM UTC] Multi domain='DNS:www.starzen.space,DNS:starzen.space'
[Sun 25 Sep 2022 05:50:05 PM UTC] Getting domain auth token for each domain
[Sun 25 Sep 2022 05:50:08 PM UTC] Getting webroot for domain='www.starzen.space'
[Sun 25 Sep 2022 05:50:08 PM UTC] Getting webroot for domain='starzen.space'
[Sun 25 Sep 2022 05:50:08 PM UTC] www.starzen.space is already verified, skip http-01.
[Sun 25 Sep 2022 05:50:08 PM UTC] Verifying: starzen.space
[Sun 25 Sep 2022 05:50:12 PM UTC] Pending
[Sun 25 Sep 2022 05:50:15 PM UTC] Success
[Sun 25 Sep 2022 05:50:15 PM UTC] Verify finished, start to sign.
[Sun 25 Sep 2022 05:50:15 PM UTC] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/590255196/128806215177'
[Sun 25 Sep 2022 05:50:16 PM UTC] Downloading cert.
[Sun 25 Sep 2022 05:50:16 PM UTC] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/03ff6b1b76f8516165032c6c2e02205a529b'
[Sun 25 Sep 2022 05:50:17 PM UTC] Cert success.
-----BEGIN CERTIFICATE-----
Lotsofcrazytext
-----END CERTIFICATE-----
[Sun 25 Sep 2022 05:50:17 PM UTC] Your cert is in  /shared/letsencrypt/www.starzen.space/www.starzen.space.cer 
[Sun 25 Sep 2022 05:50:17 PM UTC] Your cert key is in  /shared/letsencrypt/www.starzen.space/www.starzen.space.key 
[Sun 25 Sep 2022 05:50:17 PM UTC] The intermediate CA cert is in  /shared/letsencrypt/www.starzen.space/ca.cer 
[Sun 25 Sep 2022 05:50:17 PM UTC] And the full chain certs is there:  /shared/letsencrypt/www.starzen.space/fullchain.cer 
[Sun 25 Sep 2022 05:50:17 PM UTC] Installing key to:/shared/ssl/www.starzen.space.key
[Sun 25 Sep 2022 05:50:17 PM UTC] Installing full chain to:/shared/ssl/www.starzen.space.cer
[Sun 25 Sep 2022 05:50:17 PM UTC] Run reload cmd: sv reload nginx
ok: run: nginx: (pid 579) 35281s
[Sun 25 Sep 2022 05:50:17 PM UTC] Reload success
[Sun 25 Sep 2022 05:50:18 PM UTC] Domains not changed.
[Sun 25 Sep 2022 05:50:18 PM UTC] Skip, Next renewal time is: Wed 23 Nov 2022 10:01:01 AM UTC
[Sun 25 Sep 2022 05:50:18 PM UTC] Add '--force' to force to renew.
[Sun 25 Sep 2022 05:50:18 PM UTC] Installing key to:/shared/ssl/www.starzen.space_ecc.key
[Sun 25 Sep 2022 05:50:18 PM UTC] Installing full chain to:/shared/ssl/www.starzen.space_ecc.cer
[Sun 25 Sep 2022 05:50:18 PM UTC] Run reload cmd: sv reload nginx
ok: run: nginx: (pid 579) 35282s
[Sun 25 Sep 2022 05:50:18 PM UTC] Reload success

Major success !!!, curl est beaucoup plus gentil maintenant et me donne la redirection :

blah discourse % curl https://starzen.space

301 Moved Permanently
nginx/1.21.6

Et https://starzen.space dans Firefox et Chrome fonctionne maintenant, redirigeant vers le bon sous-domaine, mais j’obtiens toujours le redoutable graphique de la mort dans Safari, qu’est-ce qui se passe ? J’ai même redémarré, vidé les caches pour ce site :

En regardant le certificat depuis le navigateur, je vois :

1 « J'aime »

J’avais l’intention d’examiner cela de plus près. Je pense qu’il y a maintenant deux endroits dans le modèle Let’s Encrypt où le domaine supplémentaire doit être ajouté. Je ne pense pas que vous ayez besoin d’apporter des modifications à la configuration Nginx car elle effectue déjà une redirection 301 vers tout ce qui n’est pas le nom d’hôte.

Ce qu’il faut faire, c’est examiner le modèle Let’s Encrypt et voir où il place le nom d’hôte et s’assurer que vous faites de même avec le nom d’hôte supplémentaire.

3 « J'aime »

Oui, merci, je l’ai fait par souci de complétude et cela ne semble pas encore causer de tort, mais je suis prêt à reconstruire sans cela à un moment donné.

Il semble y avoir deux ensembles de fichiers cryptographiques ? :

root@starship-enterprise:/shared/letsencrypt# cd starzen.space
root@starship-enterprise:/shared/letsencrypt/starzen.space# ls
backup	ca.cer	fullchain.cer  starzen.space.cer  starzen.space.conf  starzen.space.csr  starzen.space.csr.conf  starzen.space.key
root@starship-enterprise:/shared/letsencrypt/starzen.space# cd ..
root@starship-enterprise:/shared/letsencrypt# cd www.starzen.space
root@starship-enterprise:/shared/letsencrypt/www.starzen.space# ls
backup	    ca.cer	   www.starzen.space.cer   www.starzen.space.csr       www.starzen.space.key
backup_two  fullchain.cer  www.starzen.space.conf  www.starzen.space.csr.conf
root@starship-enterprise:/shared/letsencrypt/www.starzen.space# 

Ah, est-ce que cela pourrait être ici (et ci-dessous)

Il n’inclut que les informations pour le nom d’hôte, pas l’apex ?

1 « J'aime »

Non, je pense que c’est correct ? Il ne devrait y avoir qu’un seul certificat et il devrait fonctionner à la fois pour www. et pour l’apex.

Cet outil suggère qu’il n’y a qu’un seul domaine sur mon certificat public (ce qui serait la source du problème ?) :

1 « J'aime »

Vous devez modifier la partie de Let’s Encrypt qui obtient le certificat. Il faut demander le certificat unique pour les deux domaines. Ces instructions fonctionnaient auparavant, mais quelque chose a changé dans la façon dont le certificat est demandé, je pense. S’il obtient le bon certificat, tout le reste fonctionne.

1 « J'aime »

Si vous exécutez certbot certificates, il affichera votre ou vos certificats et le ou les domaines qu’ils couvrent. S’il ne couvre pas à la fois le domaine racine et le www, vous pouvez

  1. exécuter à nouveau certbot et lui faire créer un certificat pour le domaine racine et le www ;

Si vous choisissez cette option, exécutez certbot certificates pour obtenir le nom du certificat que vous souhaitez supprimer. Exécutez certbot delete (nom du certificat que vous souhaitez supprimer). Il ne devrait vous rester que votre nouveau certificat (avec le domaine racine et le www).

ou (le plus simple)

  1. exécutez `certbot --expand -d existing.domain -d added.domain

Cela mettra à jour votre certificat avec un nouveau certificat contenant le domaine d’origine et ceux que vous ajoutez avec le drapeau -d.

2 « J'aime »

Jim, la commande certbot est introuvable ? fait-elle partie de l’installation standard et il y a juste un problème de chemin ?

1 « J'aime »

Sans regarder réellement… Je pense que certbot est ce que vous utilisez normalement, mais à l’intérieur du conteneur, discourse utilisait acme.

Et aussi, en relation, essayez-vous cela à l’intérieur ou à l’extérieur du conteneur ?

(Aussi, ma journée se remplit et je ne pourrai peut-être pas examiner cela aussi attentivement que je l’avais pensé, mais cela a été sur ma liste)

3 « J'aime »

D’accord… une façon de faire, je crois, est celle-ci ? :

Si j’utilise depuis n’importe quelle ligne de commande Linux appropriée

true | openssl s_client -connect www.starzen.space:443 2>/dev/null \
| openssl x509 -noout -text \
| perl -l -0777 -ne '@names=/\\bDNS:([^\\s,]+)/g; print join("\\n", sort @names);'

Je n’obtiens qu’un seul domaine et il manque l’apex.

1 « J'aime »

À l’intérieur du conteneur, vous trouvez le code qui demande (et renouvelle ?) le certificat et constatez qu’il le demande pour les deux domaines.

1 « J'aime »

Oui, c’est le cas, comme indiqué dans :

LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh --issue $2 -d www.starzen.space -d starzen.space --keylength

Et vous pouvez le voir dans la sortie du journal ci-dessus.

Cependant, il existe d’autres étapes d’installation de certificat qui n’incluent que -d www.starzen.space, ce qui pourrait poser problème ? Bien que si ce certificat est construit pour les deux, ce n’est peut-être pas le problème…

1 « J'aime »

C’est ce que j’essayais de dire. Il semble que vous deviez également mettre à jour ceux-ci. Je ne suis pas sûr pourquoi il y en a maintenant plusieurs, mais le message initial doit être mis à jour avec le code pour modifier toutes ces étapes. Du moins, c’est ce que je pense.

4 « J'aime »

Ouais, je vais essayer ça, d’abord manuellement

2 « J'aime »

Tant mieux. C’est ce que j’allais faire. Peut-être que je vous ai incité à le faire. :winking_face_with_tongue:

1 « J'aime »

C’est judicieux d’essayer, seulement je devrai peut-être reconstruire le conteneur pour installer nano… :sweat_smile:

1 « J'aime »

Non !

 apt-get update ; apt-get install nano

Vous pouvez simplement exécuter cela à l’intérieur du conteneur. Je le fais tout le temps (sauf que j’utilise vim)

3 « J'aime »

Malheureusement, cela n’a pas fonctionné :

root@starship-enterprise:/etc/runit/1.d# ./letsencrypt 
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
[Mon 26 Sep 2022 12:35:54 PM UTC] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Mon 26 Sep 2022 12:35:54 PM UTC] Creating domain key
[Mon 26 Sep 2022 12:35:56 PM UTC] The domain key is here: /shared/letsencrypt/www.starzen.space/www.starzen.space.key
[Mon 26 Sep 2022 12:35:56 PM UTC] Multi domain='DNS:www.starzen.space,DNS:starzen.space'
[Mon 26 Sep 2022 12:35:56 PM UTC] Getting domain auth token for each domain
[Mon 26 Sep 2022 12:35:59 PM UTC] Getting webroot for domain='www.starzen.space'
[Mon 26 Sep 2022 12:35:59 PM UTC] Getting webroot for domain='starzen.space'
[Mon 26 Sep 2022 12:35:59 PM UTC] www.starzen.space is already verified, skip http-01.
[Mon 26 Sep 2022 12:35:59 PM UTC] starzen.space is already verified, skip http-01.
[Mon 26 Sep 2022 12:36:00 PM UTC] Verify finished, start to sign.
[Mon 26 Sep 2022 12:36:00 PM UTC] Lets finalize the order.
[Mon 26 Sep 2022 12:36:00 PM UTC] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/590255196/129044627717'
[Mon 26 Sep 2022 12:36:01 PM UTC] Downloading cert.
[Mon 26 Sep 2022 12:36:01 PM UTC] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/03ffc90cecd2f11f2ba386da2d501127aee5'
[Mon 26 Sep 2022 12:36:02 PM UTC] Cert success.
-----BEGIN CERTIFICATE-----
phewbigcert
-----END CERTIFICATE-----
[Mon 26 Sep 2022 12:36:02 PM UTC] Your cert is in  /shared/letsencrypt/www.starzen.space/www.starzen.space.cer 
[Mon 26 Sep 2022 12:36:02 PM UTC] Your cert key is in  /shared/letsencrypt/www.starzen.space/www.starzen.space.key 
[Mon 26 Sep 2022 12:36:02 PM UTC] The intermediate CA cert is in  /shared/letsencrypt/www.starzen.space/ca.cer 
[Mon 26 Sep 2022 12:36:02 PM UTC] And the full chain certs is there:  /shared/letsencrypt/www.starzen.space/fullchain.cer 
[Mon 26 Sep 2022 12:36:02 PM UTC] Installing key to:/shared/ssl/www.starzen.space.key
[Mon 26 Sep 2022 12:36:02 PM UTC] Installing full chain to:/shared/ssl/www.starzen.space.cer
[Mon 26 Sep 2022 12:36:02 PM UTC] Run reload cmd: sv reload nginx
ok: run: nginx: (pid 2970) 329s
[Mon 26 Sep 2022 12:36:02 PM UTC] Reload success
[Mon 26 Sep 2022 12:36:03 PM UTC] Domains not changed.
[Mon 26 Sep 2022 12:36:03 PM UTC] Skip, Next renewal time is: Wed 23 Nov 2022 10:01:01 AM UTC
[Mon 26 Sep 2022 12:36:03 PM UTC] Add '--force' to force to renew.
[Mon 26 Sep 2022 12:36:04 PM UTC] Installing key to:/shared/ssl/www.starzen.space_ecc.key
[Mon 26 Sep 2022 12:36:04 PM UTC] Installing full chain to:/shared/ssl/www.starzen.space_ecc.cer
[Mon 26 Sep 2022 12:36:04 PM UTC] Run reload cmd: sv reload nginx
ok: run: nginx: (pid 2970) 331s
[Mon 26 Sep 2022 12:36:04 PM UTC] Reload success

Ce qui semble toujours avoir exposé un certificat avec un seul domaine…

true | openssl s_client -connect www.starzen.space:443 2>/dev/null \
| openssl x509 -noout -text \
| perl -l -0777 -ne '@names=/\\bDNS:([^\\s,]+)/g; print join("\n", sort @names);'
www.starzen.space
1 « J'aime »