---
title: "How to point a custom domain at GitHub Pages"
slug: "point-a-custom-domain-at-github-pages"
category: "howto"
tags: ["howto", "dns", "github-pages", "custom-domain", "https", "ops"]
status: "stable"
last_updated: 2026-09-27
summary: "The dependency-ordered steps to attach a custom domain to a GitHub Pages site: register the domain in Pages settings, verify it, add apex A/AAAA and www CNAME records, confirm with dig, then enforce HTTPS."
related: ["[[howto/launch-a-new-site]]", "[[howto/deploy-quartz-site]]", "[[ops/github-pages]]", "[[ops/namecheap-dns]]", "[[ops/cloudflare-dns]]", "[[cheatsheets/http-status-codes]]"]
---

## 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 [[howto/launch-a-new-site|zero-to-indexed launch runbook]]. It assumes the site already serves on its default `*.github.io` URL; if it does not, finish [[howto/deploy-quartz-site|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 [[ops/github-pages|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 [[ops/namecheap-dns|Namecheap DNS]] and [[ops/cloudflare-dns|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:

```bash
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:

```bash
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 [[cheatsheets/http-status-codes|HTTP status codes]] if either returns something else.

## Related

- [[howto/launch-a-new-site]]; the full launch runbook this phase belongs to
- [[howto/deploy-quartz-site]]; get the site serving on the default URL first
- [[ops/github-pages]]; the `CNAME` file pattern and Pages deploy details
- [[ops/namecheap-dns]]; entering the records at Namecheap
- [[ops/cloudflare-dns]]; entering the records behind Cloudflare
- [[cheatsheets/http-status-codes]]; reading the `curl -I` output
