Overview

Attaching a custom domain to GitHub Pages is the phase of a site launch where order matters most. The certificate machinery, the domain verification, and the DNS records each depend on the step before, and running them out of order is the usual cause of a greyed-out “Enforce HTTPS” box or a cert that covers the apex but not www.

This page is phase 3 of the zero-to-indexed launch runbook. It assumes the site already serves on its default *.github.io URL; if it does not, finish Deploy a Quartz site to GitHub Pages first so DNS problems are not tangled with build problems.

Register the domain at the host before touching DNS

Add the custom domain in the host settings first: GitHub, repo, Settings, Pages, Custom domain. This writes the CNAME file (branch deploys) or registers the domain (Actions deploys), so the cert machinery knows the domain exists when the records start resolving. On an Actions deploy, keep a CNAME file in the build output as well so a deploy cannot unset the domain; the pattern is in GitHub Pages deployment.

Verify the domain to block takeover

Verify the domain at the account or org level. GitHub gives you a TXT record to add at the registrar. Domain verification stops another GitHub user from claiming a subdomain of yours that points at Pages but has no repo attached, and it takes two minutes.

Add the apex and www records

Point the bare domain (example.com) at the four GitHub Pages IPv4 addresses with A records:

  • 185.199.108.153
  • 185.199.109.153
  • 185.199.110.153
  • 185.199.111.153

Add the matching AAAA records for IPv6 alongside them:

  • 2606:50c0:8000::153
  • 2606:50c0:8001::153
  • 2606:50c0:8002::153
  • 2606:50c0:8003::153

Point www at <user-or-org>.github.io with a CNAME record. GitHub recommends configuring www even when the apex is the canonical host, and Pages redirects between the two once both resolve.

Registrar-specific record entry lives in Namecheap DNS and Cloudflare DNS. If Cloudflare proxies the records, set SSL/TLS mode to Full (strict).

Confirm resolution before enforcing HTTPS

Wait for propagation, then check each record from the command line rather than trusting the settings page:

dig +short example.com          # four 185.199.x.153 addresses
dig +short AAAA example.com     # four 2606:50c0:800x::153 addresses
dig +short www.example.com      # <user-or-org>.github.io. then the IPs

Enforce HTTPS last

Check “Enforce HTTPS” in Pages settings only after both apex and www resolve; the box stays unavailable until then. The certificate covers whatever resolved when it was issued. If you add www after the cert was generated for the apex alone, remove and re-add the custom domain to force a fresh cert that covers both.

Finish with a header check on both hosts:

curl -I https://example.com
curl -I https://www.example.com

Both should return 200 (or a single redirect to the canonical host) with a valid certificate and no redirect loop. See HTTP status codes if either returns something else.