github pages + cloudflare 301重定向修复手记
上周末,我的个人博客 let-ai.com
在Google Search Console中收到了“重定向错误”的警告。这触发了一场长达数小时的问题排查,最终问题核心锁定在一个经典的现代Web架构冲突上:GitHub Pages的HTTPS强制策略、Cloudflare的代理规则与Hexo静态生成器的部署流程,三者间产生了意料之外的相互抵消。本文将复盘整个排查与修复过程。
问题表象:搜索引擎的“重定向错误”警告
最初,症状很明确:Google认为我的网站 let-ai.com 存在不正确的重定向。使用 curl 命令进行诊断,发现了第一个异常:
1 | curl -I http://let-ai.com |
这意味着,当用户或搜索引擎通过HTTP协议访问时,网站没有返回一个标准的永久重定向(301)到HTTPS版本,这不利于SEO权重传递和用户体验。
第一层排查:GitHub Pages配置与DNS记录
我的网站 let-ai.com 托管在 GitHub Pages 上,背后是 twoken404.github.io 仓库,并使用 Cloudflare 管理DNS和提供CDN加速。因此,排查从这两处开始。
- GitHub Pages设置:进入仓库的
Settings -> Pages,发现“Custom domain”一栏有时为空,有时设置了let-ai.com,但下方的 “Enforce HTTPS” 复选框经常是灰色不可选状态。这是关键线索,表明GitHub无法为此域名自动签发SSL证书。 - Cloudflare DNS检查:在Cloudflare控制台检查
let-ai.com的DNS记录。发现了一条CNAME记录指向twoken404.github.io,但代理状态为“DNS only”(灰色云朵)。这意味着Cloudflare只负责DNS解析,流量没有经过它的代理网络,直接到达GitHub。
第二层深入:ssl证书失败
单独看每项配置似乎都没大问题,但组合起来就形成了死结:
- 症结一:证书签发失败。GitHub Pages要为自定义域名启用HTTPS,其合作方(Let‘s Encrypt)需要能通过HTTP访问到你的域名以验证所有权。但由于我的DNS是“DNS only”,验证请求可能无法可靠抵达GitHub,导致证书签发失败,从而“Enforce HTTPS”选项失效。
- 症结二:缺少代理层重定向。Cloudflare的“Always Use HTTPS”重定向功能,必须在代理开启(Proxied)状态下才生效。我的“DNS only”设置使得这一层重定向完全缺失。
第三层意外:Hexo部署流程的“副作用”
在修复DNS,将代理状态改为“Proxied”,并成功在GitHub Pages启用HTTPS后,问题曾一度解决。但几天后,自定义域名设置再次从GitHub页面中消失。
经过复盘,发现了一个隐藏的“操作冲突”:我使用 Hexo 静态博客框架,通过 hexo deploy 命令部署。该命令会将本地 public 文件夹的内容推送到GitHub仓库的gh-pages分支。而GitHub Pages的在线域名设置,实质上是在该分支根目录自动生成一个 CNAME 文件。
冲突就在这里:我的Hexo本地项目源文件中,没有包含 CNAME 文件。因此,每次执行 hexo deploy,新生成的 public 文件夹(不含CNAME文件)都会覆盖GitHub上的gh-pages分支,顺手就把GitHub自动生成的 CNAME 文件删除了。这个文件一消失,GitHub Pages就认为我取消了自定义域名,于是设置页面里的记录也随之清空。
最终解决方案
修复需要确保三个地方的配置一致且稳固:
- Cloudflare:确保
let-ai.com的CNAME记录代理状态为 “Proxied”(橙色云朵)。这将激活Cloudflare的“Always Use HTTPS”功能,在边缘网络完成第一道301重定向。 - GitHub Pages:在仓库设置页重新添加
let-ai.com域名,并等待其自动签发SSL证书,然后务必勾选“Enforce HTTPS”。这确保了源站层面的安全强制。 - Hexo本地项目:在Hexo项目源文件的
source/目录根层级下,手动创建一个CNAME文件,内容只有一行:let-ai.com。这样,每次执行hexo generate,这个文件都会被复制到public文件夹,从而在部署时能永久保留在GitHub仓库中,与在线设置形成互补,防止被覆盖。