Skip to content

letsencrypt updates: renew location for .well-known, add support for multiple hostnames #992

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 19, 2025

Conversation

featheredtoast
Copy link
Member

@featheredtoast featheredtoast commented Aug 2, 2025

add comma-separated DISCOURSE_HOSTNAME_ALIASES to handle multiple aliases
for letsencrypt domain generation over env vars

FIX: add letsencrypt renew location for .well-known and allow for multi-domain renewal
Do not redirect to https on .well-known location for any domain
so letsencrypt cert renewals can work properly.

FIX: better listening for ipv6 for ipv4 only
Current letsencrypt assumes ipv6 in config. Check for ipv6 before listening

@pfaffman
Copy link
Contributor

pfaffman commented Aug 2, 2025

Will this let all requests get through and not just those for the discourse hostname? I think so, but I'm not quite sure

I'm trying to get certs for additional domains. The old way no longer works.

@featheredtoast
Copy link
Member Author

I'm working on that now but it is unrelated - this doesn't change anything about how the initial cert retrieval is done, but it does fix the renewal, in the case where a Discourse site installed with letsencrypt and is left alone for 3 months (the current validity of certs), it can autorenew.

add comma-separated DISCOURSE_HOSTNAME_ALIASES to handle multiple aliases
for letsencrypt domain generation over env vars

FIX: add letsencrypt renew location for .well-known
and allow for multi-domain renewal

Add /.well-known location in /var/www/discourse/public.
Allow .well-known on http to continue to serve traffic without redirects
Allows for letsencrypt cert renewals to work properly.

With DISCOURSE_HOSTNAME of example.com...

multiple domains are not able to renew if they cannot access such as
http://alternate.example.com

...which redirects under the current https config.

FIX: better listening for ipv6 for ipv4 only
Current letsencrypt assumes ipv6 in config. Check for ipv6 before listening
@featheredtoast featheredtoast force-pushed the letsencrypt-renew-location branch from 7e580b2 to 06a522c Compare August 3, 2025 03:55
@featheredtoast featheredtoast changed the title FIX: add letsencrypt renew location for .well-known letsencrypt updates: renew location for .well-known, add support for multiple hostnames Aug 3, 2025
@featheredtoast
Copy link
Member Author

PR has been updated to also include support for multi-domain certs.

@pfaffman
Copy link
Contributor

pfaffman commented Aug 3, 2025

DUDE! That is so awesome! I can't wait to check it out.

@discoursebot
Copy link

This pull request has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/set-up-let-s-encrypt-with-multiple-domains-redirects/56685/171

@discoursebot
Copy link

This pull request has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/daily-summary-9pm-utc/291850/583

Copy link
Member

@andrewschleifer andrewschleifer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of the commented out multi_accept line? @tgxworld git blame tracks this to d41b7e6.

@@ -19,6 +19,20 @@ run:
LE_WORKING_DIR="${LETSENCRYPT_DIR}" ./acme.sh --upgrade --auto-upgrade
LE_WORKING_DIR="${LETSENCRYPT_DIR}" ./acme.sh --set-default-ca --server letsencrypt

cat << EOF > /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In, for example, samples/web_only.yml, we tell operators to uncomment both web.ssl.template.yml and web.letsencrypt.ssl.template.yml.

However, the configure-letsencrypt and configure-ssl scripts are writing to the same outlet. So future changes to the latter are going to be mysteriously overwritten by the former.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair point - perhaps something simple we could do is bundle the /.well-known passthrough location into the base ssl template? It's not a path used by Discourse anywhere, and maybe it's... well known... enough that it's OK to have in the base ssl template.

@@ -51,6 +64,12 @@ run:
}
EOF

if [ -f "/proc/net/if_inet6" ] ; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this file exist if IPv6 is enabled but no interfaces have v6 addresses?

We want to listen on :: even if there are current addresses, in case one appears in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll admit this was a somewhat blind attempt at mimicking what the web_ssl does here:

if [ -f "/proc/net/if_inet6" ] ; then
sed -i 's/listen 80;/listen 80;\nlisten [::]:80;/g' /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf
sed -i 's/listen 443 ssl;/listen 443 ssl;\nlisten [::]:443 ssl;/g' /etc/nginx/conf.d/outlets/server/20-https.conf
fi

But if this isn't necessary, perhaps we can remove the references in both places and simplify everywhere

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't actually know what the behavior is when IPv6 is enabled but not configured anywhere. Maybe that if test is OK?

If listen [::]:80 does not error when IPv6 is not available that sure looks like the cleanest option. I'll try and figure out a test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Survey says "yes". The default install on Debian has listen [::]:80 default_server; Running echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6 turned off IPv6. The service still starts fine afterwards.

* Bundle well-known location http passthrough into base ssl template.
* Always configure to listen on ipv4 and v6
@featheredtoast
Copy link
Member Author

@andrewschleifer updated with feedback, let me know if that looks better.

@featheredtoast featheredtoast merged commit ae4887a into main Aug 19, 2025
5 checks passed
@featheredtoast featheredtoast deleted the letsencrypt-renew-location branch August 19, 2025 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants