Logo

GitHub Pages 迁移到 Cloudflare Pages 完整指南

Published on
...
Authors

为什么要迁移?

在使用 GitHub Pages 托管个人博客近一年后,我决定迁移到 Cloudflare Pages。主要有两个核心诉求:

1. 全球 CDN 加速

GitHub Pages 虽然可靠,但在某些地区的访问速度并不理想。Cloudflare Pages 自带全球 CDN,在全球 300+ 个节点自动分发内容,能显著提升网站的全球访问速度。

2. 细粒度的访问权限控制

这是迁移的最重要原因。我希望博客能支持以下场景:

  • 公开内容:技术文章、阅读笔记等,所有人可见
  • 私密内容:生活随想、家庭照片/视频等,仅授权好友可访问

GitHub Pages 是完全公开的静态托管服务,无法实现访问控制。而 Cloudflare Pages 结合 Cloudflare Access,可以轻松实现基于邮箱白名单、Google OAuth 等多种方式的权限管理。

技术方案对比

特性GitHub PagesCloudflare Pages
CDN 分发依赖 GitHub 节点全球 300+ CDN 节点
访问控制❌ 无✅ Cloudflare Access
自定义域名✅ 支持(需 CNAME)✅ 支持(DNS 集成)
构建速度~2-3 分钟~1-2 分钟
部署方式GitHub ActionsGit 集成自动部署
免费额度无限500 次构建/月
HTTPS✅ 自动✅ 自动 + Flexible SSL
构建环境Ubuntu RunnerCloudflare Workers 环境

迁移步骤

第一步:准备 Cloudflare Pages 项目

  1. 登录 Cloudflare 控制台 访问 dash.cloudflare.com,进入 Pages 服务

  2. 创建新项目

    • 点击 Create a project
    • 选择 Connect to Git
    • 授权 Cloudflare 访问你的 GitHub 仓库
    • 选择博客仓库(如 geekhuashan/blog
  3. 配置构建设置

    Framework preset: Hugo
    Build command: hugo --gc --minify
    Build output directory: public
    Root directory: (留空)
    
    环境变量:
    HUGO_VERSION: 0.135.0
    

    注意:务必设置 HUGO_VERSION 环境变量,否则 Cloudflare 会使用较旧的 Hugo 版本,可能导致构建失败。

  4. 首次部署 保存后 Cloudflare 会自动触发首次构建。你可以在 Deployments 页面查看实时日志。

第二步:配置自定义域名

假设你的域名是 geekhuashan.com,且 DNS 已托管在 Cloudflare:

  1. 在 Cloudflare Pages 中添加自定义域名

    • 进入项目的 Custom domains 页面
    • 点击 Set up a custom domain
    • 输入 geekhuashan.comwww.geekhuashan.com
  2. 自动配置 DNS 记录 Cloudflare 会自动创建 CNAME 记录指向你的 Pages 项目:

    geekhuashan.com       CNAME   blog.pages.dev
    www.geekhuashan.com   CNAME   blog.pages.dev
    
  3. 等待 SSL 证书生效 通常 1-5 分钟内,Cloudflare 会自动签发 SSL 证书。

第三步:移除 GitHub Pages 配置

完成 Cloudflare Pages 部署并验证正常后,可以清理 GitHub 仓库中的相关配置:

  1. 删除 GitHub Actions 工作流

    rm .github/workflows/hugo.yml
    git commit -m "移除 GitHub Actions 工作流,完全迁移到 Cloudflare Pages"
    
  2. 删除 CNAME 文件(如果有) GitHub Pages 使用根目录或 static/ 下的 CNAME 文件指定自定义域名,Cloudflare Pages 不需要此文件:

    rm CNAME  # 或 rm static/CNAME
    git commit -m "Delete CNAME"
    
  3. 关闭 GitHub Pages

    • 进入仓库 SettingsPages
    • Source 下拉菜单选择 None
    • 保存设置

第四步:实现私密内容访问控制

这是迁移的核心价值。Cloudflare Access 允许你对特定路径设置访问策略。

4.1 开启 Cloudflare Access

  1. 在 Cloudflare 控制台左侧菜单,进入 Zero Trust
  2. 首次使用需要设置一个团队名称(如 geekhuashan-team
  3. 进入 AccessApplications

4.2 创建访问策略

假设你希望保护 /posts/life/ 路径下的所有生活类内容:

  1. 创建 Application

    • 点击 Add an application
    • 选择 Self-hosted
    • 配置基本信息:
      Application name: 生活随想私密访问
      Session Duration: 24 hours
      Application domain: geekhuashan.com
      Path: /posts/life/*
      
  2. 配置访问策略(Policy) Cloudflare Access 支持多种认证方式,以下是几种常用方案:

    方案 A:邮箱白名单

    Policy name: 授权好友列表
    Action: Allow
    Rule:
      Include:
        Emails:
          - [email protected]
          - [email protected]
          - [email protected]
    

    方案 B:Google OAuth

    Policy name: Google 账号登录
    Action: Allow
    Rule:
      Include:
        Login Methods: Google
        Emails ending in: @gmail.com
    

    方案 C:一次性 PIN 码

    Policy name: 一次性密码访问
    Action: Allow
    Rule:
      Include:
        Login Methods: One-time PIN
        Emails:
          - verified-[email protected]
    
  3. 保存并测试 访问 https://geekhuashan.com/posts/life/baby-1026,会跳转到 Cloudflare Access 登录页面。

4.3 内容分类策略

为了更灵活的权限管理,我采用了以下内容分类结构:

content/posts/
├── tech/          # 公开:技术文章
├── read/          # 公开:阅读笔记
├── project/       # 公开:工作项目
└── life/          # 私密:生活随想(需登录)

在 Cloudflare Access 中创建对应策略:

  • 公开路径/posts/tech/*/posts/read/*/posts/project/* → 无需配置
  • 私密路径/posts/life/* → 配置邮箱白名单

4.4 多级权限控制(进阶)

如果需要更细粒度的控制,可以为不同路径设置不同策略:

Path: /posts/life/friends/*
Policy: 好友邮箱白名单

Path: /posts/life/family/*
Policy: 家人邮箱白名单

Path: /posts/life/private/*
Policy: 仅本人邮箱

第五步:优化 Hugo 配置

更新 hugo.toml 中的 baseURL,确保与 Cloudflare Pages 域名一致:

baseURL = 'https://geekhuashan.com/'

同时可以删除一些仅用于 GitHub Pages 的配置:

- [params.github]
- repo = "geekhuashan/blog"

迁移后的部署流程

迁移完成后,每次更新博客的流程变得更简单:

hugo server -D

# 2. 提交更改
git add .
git commit -m "新增文章:XXX"
git push origin main

# 3. 自动部署
# Cloudflare Pages 会自动检测到 push 事件,触发构建和部署
# 无需手动操作,1-2 分钟后生效

可以在 Cloudflare Pages 控制台实时查看部署状态:

  • 🟡 Building:正在构建
  • 🟢 Success:部署成功
  • 🔴 Failed:构建失败(查看日志排查)

实际效果

性能提升

使用 WebPageTest 测试全球访问速度:

测试节点GitHub PagesCloudflare Pages提升
东京1.2s0.3s75%
新加坡1.5s0.4s73%
悉尼2.1s0.5s76%
伦敦0.8s0.3s62%
纽约0.5s0.2s60%

访问控制效果

公开内容(如技术文章):

https://geekhuashan.com/posts/tech/tailscale-derp-guide
→ 直接访问,无需登录

私密内容(如生活随想):

https://geekhuashan.com/posts/life/baby-1026
→ 跳转到 Cloudflare Access 登录页
→ 输入授权邮箱接收 PIN→ 验证通过后访问内容
24 小时内免重复登录

踩坑记录

1. Hugo 版本不匹配

问题:部署失败,日志显示 Error: module "xxx" not found

原因:Cloudflare 默认使用较旧的 Hugo 版本(0.54.0)

解决:在项目设置中添加环境变量:

HUGO_VERSION = 0.135.0

2. baseURL 配置错误

问题:CSS/JS 资源 404,页面样式丢失

原因hugo.tomlbaseURL 仍指向 GitHub Pages 域名

解决:更新为 Cloudflare Pages 域名:

baseURL = 'https://geekhuashan.com/'

3. Cloudflare Access 无限重定向

问题:访问私密路径时无限重定向,无法进入登录页

原因:Access Policy 的 Path 配置与实际路径不匹配

解决:确保 Path 使用通配符 /posts/life/* 而不是 /posts/life

4. 构建缓存问题

问题:更新文章后,Cloudflare 部署成功但内容未更新

原因:Cloudflare Pages 缓存了旧的构建产物

解决:在项目设置中清除缓存,或在构建命令中添加 --gc 清理:

hugo --gc --minify

成本分析

Cloudflare Pages 免费额度

  • 每月构建次数:500 次(对个人博客完全够用)
  • 带宽:无限
  • 请求数:无限
  • 自定义域名:无限
  • 并发构建:1 个

Cloudflare Access 免费额度

  • 用户数:50 个免费用户
  • 应用数:无限
  • 认证方式:支持邮箱 PIN、Google、GitHub 等

对于个人博客而言,完全在免费额度内。

总结

从 GitHub Pages 迁移到 Cloudflare Pages,主要收获:

全球 CDN 加速:亚太地区访问速度提升 70%+ ✅ 灵活的访问控制:实现公开/私密内容分离 ✅ 更快的部署速度:构建时间从 3 分钟降至 1 分钟 ✅ 更好的集成体验:DNS、CDN、Access 统一在 Cloudflare 管理 ✅ 零成本:个人博客完全免费

如果你也有类似需求——既想公开分享技术内容,又想保护私人生活内容——Cloudflare Pages + Access 是一个完美的解决方案。

延伸阅读


更新日志

  • 2025-10-30:完成从 GitHub Pages 到 Cloudflare Pages 的迁移
  • 2025-10-30:配置 Cloudflare Access 实现私密内容访问控制
GitHub Pages 迁移到 Cloudflare Pages 完整指南 | 原子比特之间