给 GitHub Pages 绑定自己的子域名:从仓库设置到 DNS 解析、HTTPS 全记录

把 GitHub Pages 默认的 *.github.io 换成自己的子域名(如 www.whysoso.com)的完整流程——GitHub 仓库里填自定义域名、去注册商加 CNAME 解析、验证生效、开启强制 HTTPS,以及 Hugo 站点的 baseURL 配套修改、CNAME 防止被部署清空和 Cloudflare 代理的常见坑

GitHub Pages 默认给 *.github.io 地址,想换成自己的子域名(如 www.whysoso.com)只需两步:GitHub 仓库里声明自定义域名 + 注册商加 DNS 解析。本文用 www.whysoso.com → whyboystudy.github.io 实操为例,记录完整流程与踩坑。

第一步:GitHub 仓库里填自定义域名

进 Pages 仓库(用户页即 <用户名>.github.io)→ Settings → Pages → Custom domain,输入子域名(如 www.whysoso.com),点 Save。

GitHub 会自动在发布分支根目录生成 CNAME 文件(内容即你的域名),这是它识别自定义域的依据,别手删。

此时先别勾 Enforce HTTPS——证书未签发前强制会陷入重定向循环。

第二步:注册商加 DNS 记录

子域名只需加 1 条 CNAME 记录,指向 <用户名>.github.io(本文即 whyboystudy.github.io)。

记录要加在真正托管 DNS 的那家:看域名的 NS 指向谁。本文 whysoso.com 注册在 Spaceship,但 NS 已指向 Cloudflare,所以记录在 Cloudflare 加。

方案 A:域名在 Spaceship(自托管 DNS)

  1. Domains → 域名 → Manage → Advanced DNS。
  2. 加 1 条 CNAME:Type CNAME,Host www,Value whyboystudy.github.io,TTL Automatic。

方案 B:域名在 Cloudflare(或 NS 已指向 Cloudflare)

  1. 选域名 → 左侧 DNS → Records → Add record。
  2. 加 1 条 CNAME:Type CNAME,Name www,Target whyboystudy.github.io,TTL Auto。
  3. Proxy status 先设 DNS only(灰云),原因见常见坑。

照抄填的记录表(Cloudflare 版,本文实际用的):

Type Name 目标 Proxy
CNAME www whyboystudy.github.io DNS only(灰云)

第三步:验证生效 + 开启 HTTPS

DNS 全球生效需几分钟到几小时。验证:

1
2
nslookup -type=CNAME www.whysoso.com  # 应链到 whyboystudy.github.io
dig +short www.whysoso.com            # macOS / Linux 也可用

本文实测 www 的 CNAME 链为 whyboystudy.github.io → 185.199.108~111.153,即生效。

回到 GitHub Settings → Pages:等 DNS check 变绿勾 → GitHub 自动签发免费证书 → 证书就绪后勾 Enforce HTTPS。

第四步:Hugo 改 baseURL 并重新部署

hugo.yaml / config.toml 里的 baseURL 必须同步,否则站内链接、RSS、sitemap 仍是 .github.io:

1
baseURL = "https://www.whysoso.com/"   # 本文实际用

改完重新生成并推送(push 触发 Actions 自动部署)。

第五步:防止部署清空自定义域名(CNAME)

如果你用 GitHub Actions 部署(如 peaceiris/actions-gh-pages),会出现「每次 Action 跑完 Custom domain 变成空、跳回 *.github.io」——这是最高频的坑,本文 www.whysoso.com 就栽在这。

原因:在 Settings → Pages 填域名后,GitHub 把域名写进发布分支根目录的 CNAME 文件来记住它。但这类 Action 是「用 PUBLISH_DIR(如 ./public)强制覆盖发布分支、清掉其他文件」,而你的 public/ 里没有 CNAME → 每次部署把 GitHub 写好的 CNAME 冲掉 → 域名被清空。

修法:在 Hugo 源码的 static/CNAME 写一行域名(如 www.whysoso.com,不要多余空格或空行)。Hugo 构建时把 static/ 原样拷到 public/,于是 public/CNAME 每次都进发布分支,域名就稳了。

注意:

  • 若工作流 EXTERNAL_REPOSITORY 指向另一个仓库(本仓库只放源码、部署到 用户名.github.io),CNAME 落到那个仓库的发布分支——正是 Pages 读取的地方,无需在本仓库根放 CNAME。
  • 带 CNAME 的部署跑完后,回 Settings → Pages 把自定义域重填一次;之后分支里一直有 CNAME,再也不会被冲掉。

常见坑

Cloudflare 代理(橙云)导致证书签发失败 加记录时先 DNS only(灰云),等证书签发、站点正常后再按需开橙云(CDN 加速)。Cloudflare 的 SSL/TLS 模式设 Full(非 Flexible),否则与 GitHub 的 HTTPS 互重定向成死循环。

域名未注册就加解析 记录只对已注册、NS 已委派的域名生效。先确认 RDAP / whois 域名已存在(本文 whysoso.com 是当天在 Spaceship 注册、NS 指向 Cloudflare 后才配的)。

实战小结

whysoso.com 注册于 Spaceship → NS 指向 Cloudflare → Cloudflare 加 1 条 CNAME(www → whyboystudy.github.io)→ GitHub Pages 填 www.whysoso.com → 证书签发后 Enforce HTTPS → Hugo baseURL 改 https://www.whysoso.com/ 并重部署 → static/CNAME 锁定域名不被部署清空。核心三句:GitHub 声明域名、注册商 DNS 加 CNAME 指到 <用户名>.github.io、证书出来再强制 HTTPS。Cloudflare 用户记「先灰云后橙云、SSL 用 Full」即可。

使用 Hugo 构建
主题 Stack 由 Jimmy 设计