Set up SSL on GitHub Pages with custom domain using Azure

Since writing this post, GitHub introduced official support for HTTPS on custom domains. Check out: Custom domains on GitHub Pages gain support for HTTPS.

All of the content on this blog, as well as the elmah.io documentation site, are hosted as static content on GitHub Pages. I needed to add SSL to the URLs, but unfortunately GitHub Pages doesn't support HTTPS on custom domains (no yet at least). A popular choice for adding HTTPS, is to use the free plan on CloudFlare. It requires you to move all of your domains (subdomains + main domain) to CloudFlare, which isn't something that we want to do at this point.

I asked my Twitter followers and got a lot of suggestions. The most simple solution was also the one I ended up using: pushing a website to Azure App Services, acting as a reverse proxy in front of GitHub Pages. A home made CloudFlare, if you will. The idea is described in great detail on the RuslanY Blog.

To set it up, create a new empty ASP.NET project. I probably could have made this with ASP.NET Core, but for now, it's an old school ASP.NET app. We won't need anything but a simple rewrite rule anyway.

Create an empty ASP.NET project

When users browse the new website, I want GitHub Pages to serve the content. For that, I use a simple rewrite rule in web.config:

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Proxy" stopProcessing="true">
        <match url="(.*)" />
        <action type="Rewrite" url="http://elmahio.github.io/blog/{R:1}" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

In the example above, every request to the Azure website, returns the content from the URL http://elmahio.github.io/blog/{R:1}. {R:1} makes sure that the path on the original request is translated to the page on GitHub. As explained on the RuslanY Blog, we need to enable proxy functionality with Azure. To do so, create a new web app and upload a file named applicationHost.xdt to the site directory:

<?xml version="1.0"?>  
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">  
<system.webServer>  
<proxy xdt:Transform="InsertIfMissing" enabled="true" preserveHostHeader="false"  
reverseRewriteHostInResponseHeaders="false" />  
</system.webServer>  
</configuration>  

applicationHost.xdt uses XDT config transformations to insert the proxy element. For more information about XDT check out the blog post Web.config transformations - The definitive syntax guide. For help debugging common problems, we've created a Web.config Transformation Tester.

The easiest way to upload the file is to use Kudo, but FTP or any Azure file browser should do the trick. That's it for the proxy part. Deploy your website to the new web app on Azure:

Deploy project to Azure

I'm using the deployment feature in Visual Studio here, but you probably want to use VSTS, Octopus Deploy, Kudo or similar in production. Once deployed, Visual Studio launches your preferred browser, which now show the content from http://elmahio.github.io/blog/ when requesting the URL http://myproxy.azurewebsites.net. Actually, you have SSL support already, since all websites served by azurewebsites.net comes with a SSL certificate. We need to serve the content through a custom domain, so go set that up. I won't go into detail on how to set up custom domains on Azure, since that is already described in hundreds of blog posts.

Would your users appreciate fewer errors?

➡️ Reduce errors by 90% with elmah.io error logging and uptime monitoring ⬅️

When setup and the DNS records are propagated, I can browse the content on GibHub, using the Azure website as a proxy. It's important here, that you let GitHub serve the content on the default URL (http://organization.github.io/project/) and not on a custom domain. This means that any CNAME file you may have in your repository and/or CNAME DNS records pointing to GitHub Pages must be deleted.

For the final step, I need to set up HTTPS on the Azure web site. Doing that is also fully documented in the Azure documentation. In the case of the elmah.io blog, I've used this excellent tutorial written by Troy Hunt, to get a free SSL certificate from Let's Encrypt: Everything you need to know about loading a free Let's Encrypt certificate into an Azure website.

I assume that you are now able to browse your GitHub Pages content through HTTPS on the custom domain. The only thing left, is to redirect requests to the non-SSL version of the domain to one including SSL. Add another rule to web.config:

<rule name="RedirectToHTTPS" stopProcessing="true">
  <match url="(.*)"/>
  <conditions>
    <add input="{HTTPS}" pattern="off" ignoreCase="true"/>
  </conditions>
  <action type="Redirect" url="https://{SERVER_NAME}/{R:1}" redirectType="Permanent"/>
</rule>

Once the updated website is deployed, requests are successfully redirected to HTTPS and served from GitHub Pages. For a full example including some extra goodies, we've open sourced the reverse proxy running in front of blog.elmah.io and docs.elmah.io.

elmah.io: Error logging and Uptime Monitoring for your web apps

This blog post is brought to you by elmah.io. elmah.io is error logging, uptime monitoring, deployment tracking, and service heartbeats for your .NET and JavaScript applications. Stop relying on your users to notify you when something is wrong or dig through hundreds of megabytes of log files spread across servers. With elmah.io, we store all of your log messages, notify you through popular channels like email, Slack, and Microsoft Teams, and help you fix errors fast.

See how we can help you monitor your website for crashes Monitor your website