How to host your static site with HTTPS on GitHub Pages and CloudFlare

There has been a growing movement to get all websites to use SSL connections where possible. Nowadays, Google even uses it as a criterion for ranking websites.

I’ve written before about how to host an HTTPS website for free with StartSSL and OpenShift. However, StartSSL is very hard to use and provides very basic certificates, and setting up a website on OpenShift is a fairly technical undertaking.

There now exists a much simpler way to setup an HTTPS website with CloudFlare and GitHub Pages. This only works for static sites.

If your site is more complicated and needs a database or dynamic functionality, or you need an SHA-1 fallback certificate (explained below) then look at my other post about the OpenShift solution. However, if a static site works for you, read on.

GitHub Pages

As most developers will be aware by now, GitHub offer a fantastic free static website hosting solution in GitHub Pages.

All you have to do is put your HTML files in the gh-pages branch of one of your repositories and they will be served as a website at {username}.github.io/{project-name}.

GitHub pages minimal files

And all files are passed through the Jekyll parser first, so if you want to split up your HTML into templates you can. And if you don’t want to craft your site by hand, you can use the Automatic Page Generator.

automatic page generator themes

Websites on github.io also support HTTPS, so you can serve your site up at https://{username}.github.io/{project-name} if you want.

mytestwebsite GitHub pages

GitHub Pages also support custom domains (still for free). Just add a CNAME file to the repository with your domain name in it - e.g. mytestwebsite.robinwinslow.uk - and then go and setup the DNS CNAME to point to {username}.github.io.

mytestwebsite GitHub pages files

The only thing you can’t do directly with GitHub Pages is offer HTTPS on your custom domain - e.g. https://mytestwebsite.robinwinslow.uk. This is where CloudFlare comes in.

CloudFlare

CloudFlare offer a really quite impressive free DNS and CDN service. This free service includes some really impressive offerings, the first three of which are especially helpful for our current HTTPS mission:

The most important downside to CloudFlare’s free tier SSL is that it doesn’t include the fall-back to legacy SHA-1 for older browsers. This means that the most out-of-date (and therefore probably the poorest) 1.5% of global citizens won’t be able to access your site without upgrading their browser. If this is important to you, either find a different HTTPS solution or upgrade to a paid CloudFlare account.

Setting up HTTPS

Because CloudFlare are a CDN and a DNS host, they can do the HTTPS negotiation for you. They’ve taken advantage of this to provide you with a free HTTPS certificate to encrypt communication between your users and their cached site.

First simply setup your DNS with CloudFlare to point to {username}.github.io, and allow CloudFlare to cache the site.

mytestwebsite CloudFlare DNS setup

Between CloudFlare and your host the connection doesn’t have to be encrypted, but I would certainly suggest that it still should be. But crucially for us, this encrypted connection doesn’t actually need a valid HTTPS certificate. To enable this we should select the “Full” (rather than “Flexible” or “Strict”) option.

CloudFlare full SSL encryption

Et voilà! You now have an encrypted custom domain in front of GitHub Pages completely for free!

mytestwebsite with a secure domain

Ensuring all visitors use HTTPS

To make our site properly secure, we need to ensure all users are sent to the HTTPS site (https://mytestwebsite.robinwinslow.uk) instead of the HTTP one (http://mytestwebsite.robinwinslow.uk).

Setting up a page rule

The first step to get visitors to use HTTPS is to send a 301 redirect from http://mytestwebsite.robinwinslow.uk to https://mytestwebsite.robinwinslow.uk.

Although this is not supported with GitHub Pages, it can be achieved with CloudFlare page rules.

Just add a page rule for http://*{your-domain.com}/* (e.g. http://*robinwinslow.uk/*) and turn on “Always use HTTPS”:

CloudFlare always use HTTPS page rule

Now we can check that our domain is redirecting users to HTTPS by inspecting the headers:

$ curl -I mytestwebsite.robinwinslow.uk
HTTP/1.1 301 Moved Permanently
...
Location: https://mytestwebsite.robinwinslow.uk/

HTTP Strict Transport Security (HSTS)

To protect our users from man-in-the-middle attacks, we should also turn on HSTS with CloudFlare (still for free). Note that this can cause problems if you’re ever planning on removing HTTPS from your site.

If you’re using a subdomain (e.g. mytestwebsite.robinwinslow.uk), remember to enable “Apply HSTS policy to subdomains”.

CloudFlare: HSTS setting

This will tell modern browsers to always use the HTTPS protocol for this domain.

$ curl -I https://mytestwebsite.robinwinslow.uk
HTTP/1.1 200 OK
...
Strict-Transport-Security: max-age=15552000; includeSubDomains; preload
X-Content-Type-Options: nosniff

It can take several weeks for your domain to make it into the Chromium HSTS preload list. You can check if it’s in there, or add it again, by visiting chrome://net-internals/#hsts in a Chrome or Chromium browser and looking for the static_sts_domain setting.

That’s it!

You now have an incredibly quick and easy way to put a fully secure website online in minutes, totally for free!

By @nottrobin