# Discourse + Let's Encrypt w/ multiple hostnames

**URL:** https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987
**Category:** Support
**Created:** [January 17, 2020, 10:29pm UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987 "2020-01-17T22:29:59Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![downey](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/downey/32/166878_2.png) [@downey](https://meta.discourse.org/u/downey)
#### Post date: [January 17, 2020, 10:29pm UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/1 "2020-01-17T22:29:59Z")

</div>

When migrating (via backup) a Discourse from one hostname to another, an admin might want to keep the old hostname but have the web server rewrite requests to use the new canonical name, e.g.:

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

Unfortunately this isn’t as easy as just changing the CNAME or A record in DNS; the browser client will generate an error/warning because the hostname does not match the certificate generated by the Discourse installation via Let’s Encrypt.

On a manual installation of a web server, I’d use the **cerbot** utility to [generate a certificate with multiple names](https://www.digitalocean.com/community/tutorials/how-to-set-up-let-s-encrypt-certificates-for-multiple-apache-virtual-hosts-on-ubuntu-14-04) assigned to it. However, the Discourse configuration passes the Discourse hostname (only) to Let’s Encrypt, and there is no concept that I can see in the Discourse configuration for aliases.

**Has anyone set up such an arrangement, or have a hunch about how best to achieve it?** I would imagine it will involve some hacking of the SSL & Let’s Encrypt templates.

---

<div class="post-metadata">

### Author: ![maiki](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/maiki/32/233950_2.png) [@maiki](https://meta.discourse.org/u/maiki)
#### Post date: [January 17, 2020, 10:38pm UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/2 "2020-01-17T22:38:57Z")

</div>

Not Discourse-specific, but when I need to redirect over HTTPS I just redirect everything. Meaning having a server doing the redirect from the old address to the new. Some hosting options take care of this in the background, sometimes called a “domain redirect” or “forwarding” service.

I don’t even think about this anymore, because it is such a pain each time I’ve tried anything else. 🤔

---

<div class="post-metadata">

### Author: ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)
#### Post date: [January 17, 2020, 10:45pm UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/3 "2020-01-17T22:45:17Z")

</div>

> [@downey](#):
>
> However, the Discourse configuration passes the Discourse hostname (only) to Let’s Encrypt, and there is no concept that I can see in the Discourse configuration for aliases.

Discourse will only answer to one hostname. If you want more than one hostname - where your use case, supporting the former hostname, is the most common - then you will need to redirect the one to the other.

I recommend doing that outside of Discourse. Just create a nginx configuration that will have its own certificate, has a server\_name for the old hostname, and redirects everything to the new hostname.

---

<div class="post-metadata">

### Author: ![downey](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/downey/32/166878_2.png) [@downey](https://meta.discourse.org/u/downey)
#### Post date: [January 17, 2020, 10:49pm UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/4 "2020-01-17T22:49:09Z")

</div>

> [@michaeld](#):
>
> Discourse will only answer to one hostname.

Actually if you’re using a single-instance-per-server Docker-based installation, it will answer fine to any number of DNS entries (nginx is listening on port 80 and 443 for all hostnames), and correctly rewrite the URL to the canonical “new” hostname just fine. That part is working fine and painlessly. (Folks who are inclined to test this out could try it by adding a fake domain name to your machine’s localhost file and point it to an IP address of your favorite Discourse site.)

The only problem I am running into is the SSL warning because the rewrite respose from nginx is from [https://old.example.org/foo](https://old.example.org/foo) and sends a HTTP 302 redirect to the new URL.

> [@maiki](#):
>
> when I need to redirect over HTTPS I just redirect everything

> [@michaeld](#):
>
> I recommend doing that outside of Discourse.

I would rather not have to maintain a separate web server just to do a rewrite rule, if possible. 🙂

---

<div class="post-metadata">

### Author: ![michaeld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaeld/32/1594_2.png) [@michaeld](https://meta.discourse.org/u/michaeld)
#### Post date: [January 17, 2020, 11:00pm UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/5 "2020-01-17T23:00:30Z")

</div>

> [@downey](#):
>
> I would rather not have to maintain a separate web server just to do a rewrite rule, if possible

You don’t need to, you just need an extra `server` section in your config.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [January 17, 2020, 11:06pm UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/6 "2020-01-17T23:06:06Z")

</div>

Maybe have a look at [Set up Let’s Encrypt with multiple domains / redirects](https://meta.discourse.org/t/setting-up-let-s-encrypt-with-multiple-domains/56685)

---

<div class="post-metadata">

### Author: ![downey](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/downey/32/166878_2.png) [@downey](https://meta.discourse.org/u/downey)
#### Post date: [January 17, 2020, 11:07pm UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/7 "2020-01-17T23:07:28Z")

</div>

**Update:** Successfully configured the secondary domain name on the standalone installation, and issued a Let’s Encrypt certificate to handle both old and new names.

_Precondition: I did not yet change DNS to point folks over to the new site; I wanted things to be sure to work ahead of time. So I was using a localhost entry on my testing machine. This means I could not do a normal Let’s Encrypt verification, and instead had to use the acme.sh “DNS” method which is generally not recommended because it can’t auto-renew. This is fine for me; because I’ll be switching over within 30 day term of the “initial” (newly-issued 2-name) certificate._

1. In my `web_only.yml` file (you may be using app.yml) under the `hooks:` section, and before the plugins, added the following:

```plaintext
  after_ssl:
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d second-domain.com --keylength"

```

1. In DNS, set up a bogus/temporary TXT record for `_acme-challenge.old.example.org` with a 5-minute TTL (you could probably set it shorter) and let it propogate so to quickly make the change with the acme.sh (Let’s Encrypt) verification key.

2. Stop the site and issue a debug (test) validation to get the system aware of the new entry’s short TTL:

```plaintext
./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. Run the request for real this time without the debug setting. This will give you a warning with the value to use in DNS for the entry you created in step 2:

```plaintext
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. Update DNS and then wait 5 minutes. Yes, you should wait the whole time so you don’t run into Let’s Encrypt’s limitations.

2. Run a similar version to the last command but in `renew` mode:

```plaintext
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. You should have a confirmation. Run the following to clean things up and get the new cert in place:

```plaintext
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. Last step now that you’ve left the launcher:

```plaintext
rm -rf /var/discourse/shared/standalone/ssl
rm -rf /var/discourse/shared/standalone/letsencrypt
./launcher rebuild app

```

Once the site is back up, it should be running with the new cert. You may have to clear out your browser’s store certificates, which is left as an exercise to the reader and your favorite search engine.

Thanks to folks who pointed me in the right direction!

---

<div class="post-metadata">

### Author: ![Stephen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stephen/32/95011_2.png) [@Stephen](https://meta.discourse.org/u/Stephen)
#### Post date: [January 18, 2020, 12:19am UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/8 "2020-01-18T00:19:52Z")

</div>

This is a perfect application for a Cloudflare rule - zero server configuration. Just throw the same URL parameters at the new domain.

The orange cloud will need to be enabled for the old domain name.

---

<div class="post-metadata">

### Author: ![downey](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/downey/32/166878_2.png) [@downey](https://meta.discourse.org/u/downey)
#### Post date: [January 18, 2020, 1:41am UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/9 "2020-01-18T01:41:50Z")

</div>

> [@Stephen](#):
>
> This is a perfect application for a Cloudflare rule - zero server configuration. Just throw the same URL parameters at the new domain.

Yeah, a reverse proxy situation like Cloudflare (or I suppose your own reverse proxy of choice in front of your Discourse site) could workaround it by implementing the rewrite rules “up a level”. In this case Cloudflare was not an option for security and moral reasons. 🙂

(See above for standalone solution.)

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [February 17, 2020, 1:54am UTC](https://meta.discourse.org/t/discourse-lets-encrypt-w-multiple-hostnames/138987/10 "2020-02-17T01:54:15Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
