GitHub Pages custom domain with Cloudflare DNS

A practical setup guide for connecting a GitHub Pages site to a Cloudflare-managed custom domain, including A records, CNAME, proxy status, HTTPS, and common Search Console errors.

When I traced the 2dayapp.com setup, the repository answered one question: what gets built and deployed? Astro’s site URL is https://2dayapp.com, the public CNAME contains 2dayapp.com, and the GitHub Actions deployment writes that file again when it publishes dist.

Those files establish the intended target. They do not establish that the live DNS zone, GitHub Pages verification, DNS propagation, or HTTPS certificate is healthy. Those parts still require a dashboard or terminal check.

Connecting GitHub Pages to a Cloudflare-managed domain looks simple until it fails. The same few symptoms keep appearing:

The guide starts with the repository target, then moves outward to DNS and the live service. The commands use 2dayapp.com; replace only <username> with the GitHub account or organization name before running the CNAME checks.

What the repository target does—and does not—tell us

For this site’s apex domain, 2dayapp.com, GitHub Pages expects the domain to be configured in the repository settings and DNS to point at GitHub Pages. GitHub documents four A records for the apex domain:

185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153

GitHub also documents optional AAAA records for IPv6, but recommends keeping A records as well because IPv6 adoption is not universal.

For www.2dayapp.com, use a CNAME that points to the GitHub Pages default domain:

www  CNAME  <username>.github.io

Do not point the CNAME to a repository path such as <username>.github.io/my-repo. GitHub’s docs call out that the CNAME should point to the user or organization Pages domain without the repository name.

The order matters

The safest order is:

  1. In GitHub, open the repository.
  2. Go to Settings → Pages.
  3. Add the custom domain.
  4. Add or confirm the CNAME file if your publishing flow needs it.
  5. Add DNS records in Cloudflare.
  6. Wait for DNS propagation.
  7. Enable Enforce HTTPS when GitHub makes it available.

GitHub’s docs recommend adding the custom domain to the Pages settings before configuring DNS. The reason is security: a domain that points to GitHub Pages but is not claimed by the intended repository may create takeover risk.

Cloudflare DNS records

For the apex domain:

Type Name Content Proxy status
A @ 185.199.108.153 Proxied or DNS only
A @ 185.199.109.153 Proxied or DNS only
A @ 185.199.110.153 Proxied or DNS only
A @ 185.199.111.153 Proxied or DNS only

For www:

Type Name Content Proxy status
CNAME www <username>.github.io Proxied or DNS only

For Google Search Console or Bing verification:

Type Name Content Proxy status
TXT @ google-site-verification=... DNS only
TXT @ msvalidate.01=... DNS only

Cloudflare explains that only A, AAAA, and CNAME records can be proxied. Other records, including TXT, are DNS-only. It also says records used for domain ownership verification should not be proxied.

Should the Cloudflare proxy be on?

For ordinary web traffic, Cloudflare recommends proxying records that serve web traffic. A proxied record routes HTTP and HTTPS traffic through Cloudflare, which enables caching, WAF rules, redirects, and Cloudflare analytics.

But there are two practical cautions:

  1. If GitHub Pages is still validating the custom domain, switching to DNS-only temporarily can make the DNS target easier to inspect.
  2. Verification records such as TXT records are not web traffic and should remain DNS-only.

For a static blog, start with the simplest setup that passes GitHub Pages validation. Once the domain is stable and HTTPS works, turn on the proxy if you need Cloudflare caching, redirect rules, or WAF controls.

How to verify DNS from the terminal

Use dig to check whether the apex domain points to GitHub Pages:

dig 2dayapp.com +noall +answer -t A

Expected shape:

2dayapp.com.  300  IN  A  185.199.108.153
2dayapp.com.  300  IN  A  185.199.109.153
2dayapp.com.  300  IN  A  185.199.110.153
2dayapp.com.  300  IN  A  185.199.111.153

Check www:

dig www.2dayapp.com +noall +answer

Expected shape:

www.2dayapp.com.  300  IN  CNAME  <username>.github.io.

If Cloudflare proxy is enabled, you may see Cloudflare anycast IPs instead of GitHub’s IPs. That is normal for proxied records. When you need to debug the raw DNS target, temporarily switch the record to DNS-only.

Common errors

“Both domain and alternate name are improperly configured”

This usually means GitHub Pages cannot confirm that the apex domain and its alternate form resolve to the expected Pages target. Check both 2dayapp.com and www.2dayapp.com, not just one.

The smallest checklist:

  1. GitHub Pages custom domain is set to the final domain.
  2. The apex domain has the four GitHub Pages A records or an equivalent ALIAS/ANAME.
  3. www points to <username>.github.io, not a repository path.
  4. No stale A, AAAA, CNAME, or wildcard records conflict with the setup.
  5. DNS has had time to propagate.

GitHub notes that DNS changes can take up to 24 hours to propagate.

Search Console says the sitemap cannot be fetched

Check the sitemap directly:

curl -I https://2dayapp.com/sitemap-index.xml
curl -Ls https://2dayapp.com/sitemap-index.xml

If the response is 200 and the content type is XML, the file itself is probably fine. Search Console can still show a temporary fetch error soon after DNS, HTTPS, or sitemap changes. Submit the child sitemap as a fallback only if the index remains unavailable:

https://2dayapp.com/sitemap-0.xml

The site redirects to /repo-name

That usually means the static site was still built with the old GitHub Pages project base path. For Astro, make sure the production config uses the custom domain site URL and does not keep a repository base path after moving to an apex domain.

For a custom domain:

export default defineConfig({
  site: "https://2dayapp.com",
});

For a project page under https://username.github.io/repo-name, a base path can be correct. For https://2dayapp.com, it is usually wrong.

The setup fixed in this repository

For a static blog on GitHub Pages and Cloudflare, the small, portable setup is:

That setup keeps URLs clean, lets search data accumulate on the root domain, and leaves room to migrate later without changing article URLs.

Sources used for the setup