Dcycle Blog

Setting up encrypted custom domain (apex and www) on GitHub pages

November 15, 2023

GitHub Pages is a simple, free way to host a static website, either plain HTML, or generated by a static site generator such as Jekyll.

GitHub Pages allows you to use a custom domain, such as example.com or www.example.com, or both.

In this post we will see how to set up a custom domain with HTTPS, so that:

  • http://example.com/a/b/c redirects to https://www.example.com/a/b/c
  • https://example.com/a/b/c redirects to https://www.example.com/a/b/c
  • http://www.example.com/a/b/c redirects to https://www.example.com/a/b/c

Prerequisites

This post assumes you have a GitHub account and know how to create repos in GitHub.

Terminology

In this post we’ll use the term “apex” domain to refer to the domain in the format example.com without the www.. This is also sometimes referred to as the base or bare or root domain.

Subdomains are in the format something.example.com, and www.example.com is technically just another subdomain; although by convention it is special: generally we’ll expect websites to be be available on the the apex and www domains, and one of them to redirect to the other.

tldr;

The trick to get a certificate that covers both the www and the apex domain with GitHub Pages is to make sure the certificate is generated after both the apex and www domains correctly point to your GitHub Pages site. (If, for example, you start by getting the www domain to work with https, then you set up your A record on the apex domain, then the certificate will have been generated before the apex domain was set up, so the apex domain will not be covered by the certificate.)

If you set up the apex or www domain to point to your site after a certificate has already been generated by GitHub Pages, go to “Troubleshooting: forcing the certificate to be regenerated”, below.

Every GitHub Pages site contains a CNAME file at the same level as the root of the website (which can be the root of your GitHub repo, or the ./docs subfolder). You can either edit this CNAME file directly, or in the “Custom domain” field of the Pages section of your repo’s Settings. Both ways of editing the CNAME file will have the same effect.

The contents of your CNAME file (which is also the value of the “Custom domain” field of the Pages section of your repo’s Settings) will determine your website’s canonical domain.

  • If the ./CNAME, or ./docs/CNAME file, contains www.example.com, then GitHub will attempt to redirect example.com to www.example.com.
  • If the ./CNAME, or ./docs/CNAME file, contains example.com, then GitHub will attempt to redirect www.example.com to example.com.

In this post, we will assume that we want our canonical domain to be “www.example.com”, and “example.com” to redirect to it.

Step one: create a GitHub repo

I like to host my website pages in a subdirectory called ./docs in a GitHub repo, so that anything outside the ./docs repo (such as meta-data for the site, or development scripts) is not published; and anything inside the ./docs is published to the web.

I also like using the “master” branch, although GitHub Pages also allows you to publish your website on other branches such as gh-pages.

The simplest possible GitHub repo for a website is therefore a single index.html file in a ./docs directory, in the master branch.

We will assume that your GitHub username (or, if you are using an orgninization, your GitHub organization name) is MY_USERNAME_OR_ORGANIZATION and that your repo name is MY_REPO_NAME.

Step two: activate GitHub Pages

Go to the Pages section of your repo Settings at https://github.com/MY_USERNAME_OR_ORGANIZATION/MY_REPO_NAME/settings/pages.

  • Activate GitHub Pages
  • Select “Deploy from a branch”
  • Choose the “master” branch (or whatever branch you want to use)
  • Choose the “/docs” directory (or “/ (root)” is case you prefer to use the root directory of your repo to host your website).

I like to set the custom domain in a future step by editing the CNAME file directly, but you can also enter your canonical domain in the “Custom domain” field here.

Step three: create a CNAME file

Let’s assume you want to use the domain www.example.com as a canonical domain for your website, with example.com directing to it.

Create a file called ./docs/CNAME with the following content:

www.example.com

Step four: create a CNAME record

The way to do this depends on your registrar or DNS provider.

One of the pitfalls of CNAME records is that they must end with a dot, but certain DNS providers automatically add a dot without telling you, and others do not.

The CNAME record you’ll want for www.example.com is

MY_USERNAME_OR_ORGANIZATION.github.io.

If that does not validate, it is possible that your DNS provider automatically adds a dot, in which case you’ll want to use

MY_USERNAME_OR_ORGANIZATION.github.io

Step five: create an A record for the apex domain

Apex domains cannot have CNAME records, so we need to use one or more A records.

Most DNS providers allow you to set up a “redirect” from the apex domain to the www domain; however this will generally not set up HTTPS encryption, so that if someone visits “https://example.com”, they will see a warning in their browser, which is not what we want.

Here we will show how to create an A record; if you want to use an ALIAS, ANAME, or AAAA record please refer to the page “Configuring an apex domain” section of the page “Managing a custom domain for your GitHub Pages site”, on GitHub, on Nov. 15, 2023.

Go to your DNS provider and create an A record or IPv4 redirect for the apex domain, in our case example.com, with the following values, which correspond to the IP addresses of GitHub’s servers:

185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153

This sometimes requires adding four separate A records, or sometimes you can add a single A record with multiple values.

Step six: make sure the certificate generated by GitHub covers both your apex and www domains

Wait between one and fifteen minutes for everything to settle in, then make sure the certificates are valid:

curl -I https://terredesjeunes.org
curl -I https://www.terredesjeunes.org

In both cases, you should not be seeing a “curl failed to verify the legitimacy of the server” error.

Step seven: force HTTPS

Go to the Pages section of your repo Settings at https://github.com/MY_USERNAME_OR_ORGANIZATION/MY_REPO_NAME/settings/pages.

  • Select “Enforce HTTPS”

Step eight: test your setup

After waiting a minute or two, you should be able to test the following:

  • http://example.com/a/b/c redirects to https://www.example.com/a/b/c
  • https://example.com/a/b/c redirects to https://www.example.com/a/b/c
  • http://www.example.com/a/b/c redirects to https://www.example.com/a/b/c

Troubleshooting: forcing the certificate to be regenerated

In https://github.com/MY_USERNAME_OR_ORGANIZATION/MY_REPO_NAME/settings/pages, if you had a domain such as www.example.com before you set up the apex domain A records, or if you had a domain such as example.com before you set up the www domain CNAME record, you might have to force the certificate to be regenerated.

Here is a quick way to to do this:

  • If your “Custom domain” field contains “www.example.com”, then change it to “example.com”, wait a few minutes, and change it back to “www.example.com”, then wait 15 minutes.
  • If your “Custom domain” field contains “example.com”, then change it to “www.example.com”, wait a few minutes, and change it back to “example.com”, then wait 15 minutes.

In the former case your canonical domain will be “www.example.com”, with “example.com” redirecting to it.

In the latter case your canonical domain will be “example.com”, with “www.example.com” redirecting to it.

Resources