从零搭建:用 Cloudflare Pages 托管自己的博客
不买域名、不租服务器、不用 Git。能装 Python 的电脑 + 一个 Cloudflare 账号, 就能把博客发到公网,而且换电脑照样能更新。
这篇文章记录的是一次真实的迁移:把博客从某个托管平台搬到 Cloudflare Pages。 过程中撞了三个坑,每一个都表现为「部署显示成功,但网站打不开」—— 排查花了很久,所以把成因和验证方法都写下来。
为什么是 Cloudflare Pages
静态博客的托管选择不少,最后选 Cloudflare Pages 是因为它在几个关键点上 没有额外成本:
| 项目 | 情况 |
|---|---|
| 域名 | 免费分配 <项目名>.pages.dev,不需要买 |
| 备案 | 不需要 |
| HTTPS | 自动配置并续期 |
| 费用 | 个人博客用量在免费额度内绰绰有余 |
| 文件数上限 | 20000 个(本站 19 个) |
| 单文件上限 | 25 MiB(本站最大约 1.2 MB) |
它有两种接入方式:Git 集成(连 GitHub 仓库,push 自动构建) 和 Direct Upload(本地文件直接上传)。
⚠️ 选之前要想清楚
Direct Upload 项目创建后无法切换回 Git 集成,这是 Cloudflare 的平台限制。选错了只能新建项目。
本文走 Direct Upload 路线,因为它不需要 GitHub 账号、不需要配 SSH、 不需要装 Node.js——换电脑只要一个 Token。
准备:账号与密钥
1. 注册 Cloudflare 并验证邮箱
注册很直接,但有一点容易漏:邮箱必须完成验证, 否则后续 API 调用会失败。记得检查垃圾邮件夹。
2. 创建一个 API Token
Token 相当于一把专用钥匙,让脚本能往你的账号里传文件。 路径是:右上角头像 → My Profile → API Tokens → Create Token。
权限只需要一项:
✅ 唯一必需的权限
Account → Cloudflare Pages → Edit
用「Edit Cloudflare Workers」模板会附带一堆 Workers / KV / R2 / Containers 权限,这个场景一个都用不上,但不影响使用。
创建完成后页面会显示一串字符,只显示这一次,立刻复制。
Token 该怎么放
- 不要贴在聊天记录、笔记、公开仓库里——它等同账号权限
- 建议只建一个专用于此博客的 Token,出问题能单独吊销
- 存到系统配置目录,不要放在项目文件夹里—— 那样打包或分享项目时会顺手泄露
部署:三步 API 流程
Cloudflare 的 Direct Upload 实际上是三个接口串起来的。 理解这个流程,出问题时才知道去哪一步找原因。
-
拿一个临时上传令牌
GET /accounts/{账号}/pages/projects/{项目}/upload-token返回一个 JWT,只用于下一步传文件。它和你的 API Token 是两回事, 有效期很短。
-
把文件传到资源库
POST /pages/assets/upload注意这个路径里没有账号 ID,用上一步的 JWT 认证。 每个文件以「内容哈希 → 文件内容」的形式提交。
传完再调一次
upsert-hashes登记哈希, 这样下次部署能跳过已上传的文件。这步失败不影响本次部署。 -
创建部署
POST /accounts/{账号}/pages/projects/{项目}/deployments这一步换回你自己的 API Token。提交一个清单 (每个路径对应哪个哈希)+ 分支名,平台据此把资源组装成一次部署。
完成后会返回两个地址:一个是本次部署的专属地址(带一段短哈希),
另一个是稳定的生产域名 <项目名>.pages.dev。
验证时用哪个地址
生产域名生效有几十秒延迟,刚部署完可能还是旧的或 404。 判断部署是否成功,看专属地址更可靠。
三个坑:都表现为「成功但打不开」
下面每一条都会让接口返回 success: true、部署记录显示
success,但访问任何路径都是 404。
这也是这次排查最费时间的地方——错误信号具有误导性。
坑一:文件哈希不是 SHA-256
第一反应当然是用 SHA-256 算文件哈希。而 Cloudflare 用的是 BLAKE3,而且哈希的输入还不是文件本身:
blake3( base64(文件内容) + 扩展名 ).hex()[:32]
三个细节缺一不可:算法是 BLAKE3;输入是 base64 编码后的内容再拼上
扩展名(不含点,如 html);最后取前 32 个
十六进制字符。
⚠️ Python 标准库没有 BLAKE3
hashlib 只有 blake2,没有 blake3。
所以要自己实现一个(或者引入依赖)。
实现完必须用官方向量验证——哈希算错了,同样表现为全站 404。
坑二:清单的键必须带前导斜杠
清单是「路径 → 哈希」的映射。直觉会写成 "index.html",
但必须写成 "/index.html"。
{"/index.html": "哈希值", "/about.html": "哈希值"} ← 正确
{"index.html": "哈希值", "about.html": "哈希值"} ← 全站 404
这条最隐蔽:接口照样成功,部署记录照样成功,没有任何报错。
坑三:一个不存在的接口会「假装成功」
我一开始把取上传地址的接口写成了
/pages/projects/{项目}/upload。
它根本不存在——但 Cloudflare 不会返回 404,
而是兜底返回了项目对象。
结果就是:响应里 success 是 true,
但拿不到想要的字段,程序抛 KeyError。
正确路径是 /upload-token。
排查这类问题的最快办法
用官方 CLI wrangler 成功部署一次,把它当基线,
再对比自己的实现哪里不一样。这三个坑都是这样定位出来的。
以后怎么更新
内容改完之后跑一次部署脚本,约 20 秒上线。 生产域名永远不变,所以你分享出去的链接不会失效。
python deploy_cf.py deploy
脚本会自动完成:检查文件完整性 → 查账号 → 建项目(若不存在) → 取令牌 → 传资源 → 创建部署 → 打印网址。
⚠️ 别以「部署成功」为终点
因为上面那三个坑的存在,脚本输出的成功不等于线上可用。 改完后一定实际访问一次线上页面,而且要把主要内链都点一遍—— 只看首页会漏掉「某个文件被排除规则漏传」这类问题。
换电脑怎么办
这是这套方案真正的价值所在。
很多部署方案把配置和状态绑定在本地:某台电脑上的某个目录、某个配置文件。 换一台电脑,这些全都不认识你了,得从头配一遍—— 而托管平台往往只认「原来那台机器」,于是链接就保不住了。
这里的做法是:把状态全部推到云端。 项目在 Cloudflare 上,Token 是账号级的,本地只剩「站点文件 + 一个脚本」。
所以在新电脑上只需要:
-
复制站点文件夹过来
或者从网盘/仓库拉取,只要文件齐全就行。
-
保存一次 Token
运行
python save_token.py,粘贴 Token。 存在系统配置目录,不会随项目文件夹被复制走。 -
部署
python deploy_cf.py deploy。 因为项目已经在云端存在,脚本会直接复用它, 链接保持完全一致。
✅ 关键点
本地不需要装 Git、Node.js 或 wrangler, 也不需要任何部署凭据文件(除了那个 Token)。 只要能跑 Python 3.8+ 就能更新站点。
Windows 上还会遇到一个坑
如果你的电脑没单独装过 Python,在命令行敲 python
可能看到这句话:
Python was not found; run without arguments to install from the
Microsoft Store, or disable this shortcut from Settings > Apps >
Advanced app settings > App execution aliases.
这不是 Python 坏了,是你点到了一个假的 Python。
Windows 预置了两个占位符(其实是指向微软商店的跳转器):
AppData\Local\Microsoft\WindowsApps\python.exe。
更麻烦的是:用 where python 查找时,它会
优先找到这个假货并返回成功。所以脚本里判断
Python 是否存在,不能只用 where,
必须实际跑一次验证:
python -c "import sys" # 跑不通说明是假占位符
解决办法有三个:直接指定真实 Python 的完整路径; 在「设置 → 应用 → 高级应用设置 → 应用执行别名」里关掉那两个开关; 或者去官网装一个真的 Python(安装时记得勾选 Add Python to PATH)。
这套方案不适合什么
说清楚边界比只讲好处更有用:
- 不接受手动上传。 每次更新都要跑一次命令。 如果你想要「push 就自动部署」,那应该用 Git 集成路线, 代价是要配 GitHub 仓库。注意这是二选一,创建时就得决定。
- 没有版本历史。 每次部署覆盖上一次, 平台保留部署记录但内容以最后一次为准。想要完整历史就得靠 Git。
- 不支持需要后端的场景。 静态文件可以, 需要数据库或服务端逻辑就得用别的方案。
小结
静态博客托管其实不复杂,难点集中在几个不直观的细节上—— 哈希算法、清单格式、以及一个会「假装成功」的接口。 这些细节都不会给出明确的错误提示,只能靠理解流程和实际验证来发现。
而「换电脑可用」这件事,本质上不是技术问题,是架构选择: 把状态放在云端,本地只留可复制的文件和一把钥匙, 迁移就退化成「复制文件夹 + 粘贴一次 Token」。