博客号 BlogHao 完整部署教程
从零开始,把这套博客部署到 Cloudflare(全程可使用免费套餐)。不想把代码跑在 Cloudflare 上、想用自己的服务器?见下方「方式三:Docker 自托管」。
在线示例:https://blog.xiaowuleyi.com(作者实例;Worker 名
xwblog,数据库xwblog-db,图床桶xwblog-images,与仓库内 wrangler.jsonc 一致)。给自己部署一套时,资源名可以原样沿用,也可以自行替换——与你的 wrangler.jsonc 保持一致即可。
方式一:一键部署(推荐,全程不碰命令行)
点按钮 → 用 GitHub 账号授权 → 在设置页给 Worker、D1 数据库、R2 图床起好名字 → 点 Create and deploy。Cloudflare 会自动完成:
- 把仓库复制一份到你的 GitHub 账号(以后改代码、提 Issue 都在这份副本上)
- 按仓库内
wrangler.jsonc开通 D1 数据库与 R2 存储桶,并把新资源的 id 回填进副本的配置 - 构建并部署到 Workers,随后接管 push 自动部署(你往副本推代码,Cloudflare 自动重新部署,无需 GitHub Actions 密钥)
若账号还没用过 R2,会被要求先添加支付方式——免费额度内不扣费,只是验证。
部署完成后(约 1-2 分钟)打开 Workers 面板给出的 https://<你的 Worker 名>.<你的子域>.workers.dev:
- 访问
/admin/创建管理员(同第 4 节,首次进入即建号,欢迎文章已就位) - 进后台「设置」填站点链接(同第 5 节,绑自定义域名前可先空着,用默认 workers.dev 域)
- 想绑自定义域名 → 第 6 节;想本地开发 → 第 9 节
副本仓库里的 GitHub Actions 部署工作流(
deploy.yml)没有配置密钥,push 时会黄字警告并自动跳过——这是正常的,部署已由 Cloudflare 侧接管;想改用 Actions 部署见第 7 节。
以下第 0–7 节是方式二:命令行部署的完整步骤(想自己掌控每一步、或要写进自动化脚本时用)。
0. 准备工作
- 一个 Cloudflare 账号(免费版即可):dash.cloudflare.com 注册
- 本机安装 Node.js 18 或更高版本
- 本项目代码(clone 或 fork 后下载)
cd bloghao
npm install
npx wrangler login # 会打开浏览器授权,登录你的 Cloudflare 账号
npx wrangler whoami # 确认登录成功1. 创建 D1 数据库
npx wrangler d1 create xwblog-db输出大致如下:
[[d1_databases]]
binding = "DB"
database_name = "xwblog-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"把 database_id 复制,打开 wrangler.jsonc,替换(仓库里已填的是本站自己的 id,部署你自己的副本时换成你的):
"d1_databases": [
{
"binding": "DB",
"database_name": "xwblog-db",
"database_id": "粘贴你的 database_id"
}
]然后初始化表结构(幂等,可重复执行):
npx wrangler d1 execute DB --remote --file schema.sql2. 创建 R2 存储桶(图床)
npx wrangler r2 bucket create xwblog-imagesR2 免费额度:10GB 存储 / 每月 100 万次读、1000 万次写,个人博客绰绰有余。 不需要给桶开公开访问——图片统一通过你的 Worker 的
/images/xxx路径带缓存头输出,桶保持私有更安全。
wrangler.jsonc 里的 "bucket_name": "xwblog-images" 若改名请同步修改。
3. 首次部署
npm run deploy成功后 wrangler 会输出你的访问地址,例如:
Published xwblog v1.0.0
https://xwblog.<你的子域>.workers.dev4. 初始化管理员
浏览器打开:
https://你的域名/admin/首次访问会显示「创建管理员」页面:
- 填用户名(2-24 位字母、数字、_ 或 -)、密码(≥ 8 位)、昵称
- 点击「创建并进入」
- 系统自动生成一篇欢迎文章,你可以在后台删掉它,开始写自己的第一篇
该入口只在数据库没有任何用户时开放,之后重复访问就是普通登录页。
5. 基本设置
后台 →「设置」:
- 站点名称 / 描述 / 页脚:出现在首页刊头、浏览器标题、RSS
- 站点链接:填写最终访问域名(本站即
https://blog.xiaowuleyi.com),用于 RSS 和 sitemap 里的绝对链接。绑定了自定义域名就务必填上 - 站点头像 / 网站图标:都从后台上传、存进 R2 图床,改即时生效
- 外观:六套主题即点即换
- 评论:可开关留言、可开启「先审后展」
6. 绑定自定义域名
workers.dev 域名在国内部分地区不稳定,正式使用建议绑一个自己的域名(本站绑的就是 blog.xiaowuleyi.com)。前提:这个域名已托管在同一个 Cloudflare 账号下(即域名的 DNS 由 Cloudflare 管理)。
方法一(面板操作,推荐):Cloudflare Dashboard → Workers & Pages → xwblog → Settings → Domains & Routes → Add → Custom domain,填入 blog.你的域名.com,证书自动签发,几分钟内生效。
方法二(命令行):在 wrangler.jsonc 增加后重新 npm run deploy:
"routes": [{ "pattern": "blog.xiaowuleyi.com", "custom_domain": true }]绑定完成后还有一步别漏:后台「设置 → 站点链接」改成新域名(如 https://blog.xiaowuleyi.com)——RSS、sitemap、OG 分享卡里的绝对链接都取这个值。
7. 推上 GitHub + push 自动部署(命令行部署适用)
一键部署的副本已经由 Cloudflare Workers Builds 接管 push 自动部署,这节可以跳过。
git init
git add .
git commit -m "feat: bloghao 初始化"
# GitHub 上新建空仓库后:
git remote add origin git@github.com:<你>/bloghao.git
git branch -M main
git push -u origin main仓库已内置 .github/workflows/deploy.yml。要启用它:
- Cloudflare 面板 → My Profile → API Tokens → Create Token → 使用「Edit Cloudflare Workers」模板,并额外勾选 D1 Edit 与 R2 Edit 权限
- GitHub 仓库 → Settings → Secrets and variables → Actions,添加两个 secret:
CLOUDFLARE_API_TOKEN:上一步的令牌CLOUDFLARE_ACCOUNT_ID:面板首页右侧可以看到
- 之后每次 push 到
main,GitHub Actions 会自动:类型检查 → 安装依赖 → 执行 schema.sql(幂等)→wrangler deploy。另有内置的ci.yml与部署并行,跑类型检查 + 回归测试(tests/30+ 用例),防止已修复的 bug 悄悄复发
更省事的替代:不配任何密钥,在 Cloudflare 面板 → 你的 Worker → Settings → Git 支持(Builds)连接 GitHub 仓库,push 即自动部署(一键部署的副本默认就是这条路)。
方式三:Docker 自托管(自有服务器)
不想把代码跑在 Cloudflare 上、手头有 VPS 时,仓库内的 docker-poc/ 提供零改动的自托管方案:业务代码原样跑进一个 Node 容器,文章存进内置 SQLite(单文件、WAL 模式),图片存本地磁盘目录,也可以继续用 Cloudflare R2 桶(零出口流量费,备份自动异地)。单进程按域名同时托管多个完全独立的博客站,Cloudflare 退回只做 DNS + CDN。
git clone https://github.com/bloghao/bloghao.git
cd bloghao/docker-poc
docker compose up --build -d # 镜像约 70MB(node:26-alpine),数据落在 ./data/<域名>/要点:
- 站点配置:把真实域名写进
docker-poc/tenants.json(*.localhost只在本地有意义),重启容器生效;首次访问/admin/创建管理员,与 Workers 版完全一致 - 端口与反代:默认监听
8787;XWLBLOG_PORT=80可直接挂 80,XWLBLOG_BIND=127.0.0.1只绑回环、交给 nginx / Caddy / 1Panel 反代分流——多站点靠 Host 头识别,反代必须透传 Host - HTTPS:域名套 Cloudflare 橙云代理时,先用「灵活 SSL」回源源站 80 最快跑通;正式期建议前置 Caddy 终结 TLS,SSL 模式改「完全(严格)」
- 图片存储二选一:默认本地磁盘;tenants.json 里
storage: "r2"切换到共享 R2 桶(按域名前缀隔离),启动日志出现「[r2] 自检通过」即配置正确,--copy-local-to-r2幂等迁移存量图片 - 定时任务:定时发布(每分钟扫描)与北京时间 00:30 的备份 / 回收站清理随容器自动运行;图床桶在 R2 上时,备份快照同步变成异地备份
容量参考:4核8G / 200G NVMe 舒适跑 100 个站点(实测 3 租户单进程内存约 64MB,天花板在磁盘图片量而非 CPU / 内存)。完整部署清单(含国内镜像加速、验收明细)见 docker-poc/DEPLOY.md,架构与适配层说明见 docker-poc/README.md。
8. 日常运维备忘
| 事项 | 命令 / 操作 |
|---|---|
| 看实时日志 | npx wrangler tail |
| 手动备份 D1(导出 SQL) | npx wrangler d1 export xwblog-db --remote --output=backup.sql |
| 恢复备份 | npx wrangler d1 execute xwblog-db --remote --file=backup.sql |
| 浏览数据 | Dashboard → Storage & Databases → D1 → xwblog-db → Console |
| 重置管理员(清空用户重新创建) | npx wrangler d1 execute DB --remote --command "DELETE FROM users; DELETE FROM sessions;",再访问 /admin/ |
| 查看图片占用量 | Dashboard → R2 → xwblog-images,或后台「媒体」页 / 概览页 |
9. 本地开发
npm run db:init:local # 初始化 .wrangler/state 下的本地 D1
npm run dev # http://127.0.0.1:8787(本地 D1/R2 全模拟,不花钱)
npm run typecheck # TypeScript 类型检查,提交前必须通过
npm test # 回归测试(tests/,30+ 用例),提交前必须通过
npm run smoke # 本地冒烟:起 wrangler dev 逐路由断言 200,改 SQL 拼接/渲染后必跑本地与线上行为一致(同一套 Workers runtime)。上传的测试图片存放在本地模拟的 R2 里,不会占用线上额度。
10. 常见问题
Q:一键部署时要求添加支付方式? A:R2 图床开通的前提——免费额度(10GB 存储)内不扣费,只是账号验证,放心添加。
Q:一键部署后往副本 push,GitHub Actions 出现黄字警告「缺少 secrets」?
A:正常现象。部署已由 Cloudflare Workers Builds 接管,deploy.yml 检测到没配密钥会自动跳过,不影响任何功能;想改用 Actions 部署再按第 7 节配置。
Q:一键部署按钮点了没反应 / 授权失败? A:Deploy to Cloudflare 只支持公开仓库(本仓库即是);确认浏览器没有拦截弹窗,GitHub 授权页里勾选仓库访问权限后重试。
Q:部署时报 database_id 无效?
A:确认你填的是 wrangler d1 create 返回的 UUID,且 database_name 与实际一致(本仓库为 xwblog-db)。
Q:访问首页 500?
A:多半是没执行 d1 execute DB --remote --file schema.sql,或 wrangler.jsonc 里 D1 的 binding 名被改了(必须叫 DB)。
Q:图片上传失败?
A:确认 R2 桶名与 wrangler.jsonc 一致(xwblog-images);确认文件类型是 JPG/PNG/WebP/GIF 或 MP4/WebM,且 ≤ 25MB。
Q:workers.dev 域名在国内访问慢/被墙?
A:绑定一个自己的域名(第 6 步)通常即可解决,本站的 blog.xiaowuleyi.com 就是这么来的。
Q:绑定自定义域名后 RSS / 分享卡片里还是旧的 workers.dev 链接? A:把后台「设置 → 站点链接」改成新域名并保存。
Q:想改端口/项目名?
A:项目名改 wrangler.jsonc 的 name;本地端口 npm run dev -- --port 9000。
11. 附:官网(bloghao.com)是怎么部署的(维护者备忘)
博客号官网是与博客系统互相独立的纯静态站点,源码在仓库 website/ 目录,部署在 Cloudflare Pages 项目 bloghao(即 bloghao.pages.dev),自定义域绑定为 bloghao.com:
- 改动发布:修改
website/public/后 push 到 GitHub,Pages 项目连着bloghao仓库(构建输出目录website/public)会自动部署;也可手动cd website && npx wrangler pages deploy public - 「博客号目录」:数据在
website/public/data/showcase.json,访客通过官网入口向 bloghao 提 Issue 申请上榜,审核通过后把站点加进 JSON 即可 - 在线示例:官网指向的演示站(Worker 名 xwblog-demo,地址以部署输出为准)是引擎的另一套独立 Worker 部署,专供访客体验;作者实例 blog.xiaowuleyi.com 不作演示用
- 官网与本博客 Worker 互不影响,部署 / 回滚都在 Workers & Pages 的
bloghao项目里操作