HTTPS by DefaultMatt Palmer April 18, 2018
Here at Discourse World HQ, we’re firm believers in the value of security. We fund a public bug bounty program, and we document our security policy and procedures right in the repo. Securing traffic between a forum’s server and its users is important, too, and we’ve had first-class support for integrating Let’s Encrypt into a self-hosted Discourse server since virtually day one of their being generally available.
All of this is to explain why we’re so very proud to be able to announce that every new hosted Discourse instance now comes with HTTPS configured (and enforced via HSTS policy) by default, and the majority of our existing customers have been transparently migrated to enforced HTTPS. Some of our customers can’t be automatically HTTPS enforced; if you see your site is still loading over HTTP, please contact our support team so we can walk you through the changes that need to be made.
The Story So Far
HTTPS has always been supported by our hosting, but for a long time it wasn’t feasible to automatically roll it out to everyone. Back in the Dark Times (up to 2015 or so), SSL was a headache to do at scale, unless you were big enough to be able to wangle a special deal with a CA. Sure, certificates cost money, but that wasn’t the biggest hassle. The thing that stopped us, honestly, was the painful story around automation. Basically, there wasn’t any – not end-to-end, anyway.
It’s fun to track the evolution of our SSL procedures by looking at the titles of our runbooks over time. In the Dark Times, we went through several iterations – there was “How to install a customer’s SSL certificate”, then “Customer SSL workflow (Manual Edition)”, “Semi-Automated Customer SSL workflow”, and finally, “Customer SSL workflow (99.5% Automated Edition)”. Whilst we tried very hard to automate as much of the process as we could, getting an SSL certificate always seemed to involve a human in the loop somewhere, and when you provide automated trial signups, you can’t put a human in the middle of that process without making everything terrible.
Thankfully, Let’s Encrypt came along to bring us into the age of certificate Enlightenment. We’ve been big supporters of Let’s Encrypt for a long time; we’ve been donating the hosting for the Let’s Encrypt community forums practically since the initial public announcement, and we donate what we would have otherwise spent on certificates in cash, as well. When Let’s Encrypt became generally available, we re-implemented our SSL certificate issuance pipeline on top of that, and everything was reasonably peachy.
So, Let’s Encrypt made it easy for us to fully-automate getting SSL certificates for our customers, as they asked for it. Except, there’s a big difference between requesting a certificate for a running site, when a customer asks for it, and making sure you’re getting a certificate issued as soon as the site’s DNS is configured. Even detecting that DNS is correctly configured, given the wide variety of, shall we say, “interesting” configuration choices some people make, can be a challenge. This took a lot more time and ingenuity than getting issuance working. Requesting a certificate from Let’s Encrypt and dealing with validation is about 10 lines of Ruby (with the help of the
acme-client gem) and a bit of HAProxy magic. Dealing with all the special cases and exceptions in people’s DNS and proxy setups is quite a bit more code.
As an added challenge, a large part of our team has been hard at work since mid last year building out a completely custom, hyper-scale AWS-based hosting environment for a large game company. That work, which has now borne fruit, diverted time and attention away from building out universal SSL as quickly as we would have liked.
The Final Hurdle
The final hurdle is the problem of migration. We want all our existing customers to automatically have the benefits of our SSL labours. There’s a few things that get in the way of just flicking the switch for customers who have been with us for some time.
First off, forcing everyone to use HTTPS, via redirects and HSTS config, breaks some things. The biggest issue is the lack of a universally-supported way to say to a HTTP client, “transparently make this exact request again, but to this other URL”. There are newly-standardised HTTP response codes for “redirect with the same HTTP verb”, but they’re not supported by all browsers and HTTP libraries, and they sometimes prompt “do you want to do this again?”, which isn’t what you want for a smooth transition.
External authentication providers get in the way, too. They often whitelist the return URLs they’ll accept. When you call out to an authentication service, you typically send along a link which the browser should be redirected back to after authentication is complete. Sending an HTTPS link, when the authentication provider expects an HTTP one, results in authentication errors. Very not cool. We can’t fix this ourselves, either – we don’t have access to our customers’ Google, Facebook, and Twitter applications to update the whitelisted URL.
Finally, there’s the age-old problem of mixed-content warnings, which pretty much everyone who has stood up a HTTPS site has dealt with at one time or another. Thankfully, the vast majority of those we can fix on our customers’ behalf, by making sure the site being linked to supports HTTPS, and modifying the site config to add a strategically-placed “s”.
Security is no longer optional
Our deployment of HTTPS by default is coming at just the right time. Popular browsers such as Chrome and Firefox are in the process of rolling out changes to mark HTTP-only sites as “Not Secure”, like so:
It’s reasonable to assume that this trend will continue, with other browsers following suit, and the warnings getting more and more scary over time. So, regardless of where you’re hosted, now would be a good time to start making sure all your web properties are being served over HTTPS.
Full of win
It has been a bit of a journey, but in the end, we’ve gotten to where we want to be: new customers get HTTPS enforced by default, most existing customers have HTTPS enforced by default without their even noticing, and for the remainder, we know exactly what they need to do to complete the upgrade.