banner
约 3,900 字
13 分钟

部署本博客教程

摘要

部署一个和我一样的博客,全部免费

部署 Flare Stack Blog#

本教程转载原作者

通过 GitHub + Cloudflare Workers Builds,在浏览器中完成博客部署,并使用自己的域名访问和管理博客。

Tip

更喜欢看视频?可以跟着 B 站视频教程 一步步完成部署。

前置条件#

  • 一个 GitHub 账号。

  • 一个 Cloudflare 账号,已经绑定付款方式并开通 R2。

  • 一个已在 Cloudflare 托管、状态为 Active(有效) 的域名。

下文以 blog.example.com 为博客域名、flare-blog 为 Worker 名称,部署时替换成自己的值即可。建议使用空闲子域名,并在托管域名的 Cloudflare 账号下创建所有资源。

开始操作#

  1. Fork 仓库

  2. 准备两份变量清单

  3. 创建 GitHub OAuth App

  4. 创建 Cloudflare 资源

  5. 可选:开启图片优化

  6. 创建 Worker 并部署

  7. 登录博客,成为管理员

  8. 以后如何更新

1. Fork 仓库#

打开 du2333/flare-stack-blog,点击右上角 Fork。

GitHub 仓库右上角的 Fork 入口
GitHub 仓库右上角的 Fork 入口

在创建页面中,Owner 选择自己的 GitHub 账号,仓库名保留 flare-stack-blog,勾选 Copy the main branch only,点击 Create fork。

创建后会进入 github.com/你的用户名/flare-stack-blog,后续使用这份仓库部署。

2. 准备两份变量清单#

在 Fork 的仓库根目录中打开下面两个文件,点击 Raw 复制内容,分别保存到电脑上的两个文本文件中。也可以从下面的链接查看本项目模板:

项目模板

建议保存为

用途

最后填到哪里

.env.example

.env

构建时变量:告诉部署程序使用哪个域名和哪些资源

Cloudflare 的构建设置

.dev.vars.example

.dev.vars

运行时变量:博客运行时使用的认证配置等

Worker 的运行时变量与机密

将这两份清单保存在本地,随着后续步骤补齐变量,最后填入 Cloudflare。其中的密钥请妥善保管。

构建时必填项#

变量

示例 / 从哪里获取

作用

WORKER_NAME

flare-blog

Worker 应用名称,第 6 步的 Project name 必须与它一致

DOMAIN

blog.example.com

博客的纯域名

D1_DATABASE_ID

第 4 步复制的 Database ID / UUID

找到存放文章、用户等数据的数据库

BUCKET_NAME

blog-media

找到存放图片等文件的 R2 存储桶

QUEUE_NAME

blog-queue

找到处理通知等异步任务的队列

KV_NAMESPACE_ID

第 4 步复制的 Namespace ID

找到博客使用的缓存空间

构建清单保留上面六项,先填好 WORKER_NAME 和 DOMAIN,其余值在第 4 步补齐。模板中的可选项和本地工具变量可以跳过。

运行时必填项#

变量

应该填什么

作用

BETTER_AUTH_SECRET

自己生成的一串随机密钥,至少 32 个字符

保护登录会话等认证数据;生成后妥善保存

BETTER_AUTH_URL

https://blog.example.com

博客完整访问地址,用于登录和回调

DOMAIN

blog.example.com

运行时使用的域名,与构建时一致

GITHUB_CLIENT_ID

第 3 步获取的 Client ID

标识你的 GitHub 登录应用

GITHUB_CLIENT_SECRET

第 3 步获取的 Client Secret

GitHub 登录应用的密钥

将模板中的本地开发配置改为线上配置:

  • BETTER_AUTH_URL=http://localhost:3000 改成自己的完整 HTTPS 地址。

  • ENVIRONMENT=dev 改成 ENVIRONMENT=prod。

两份清单中的 DOMAIN 填相同的值,分别用于部署时绑定域名和博客运行时读取。

BETTER_AUTH_SECRET 可以用密码管理器生成 64 位随机字母数字。也可以在任意可信 HTTPS 页面打开浏览器开发者工具的 Console(控制台),执行下面这段代码,复制结果,不包含两边引号:

纯文本
Array.from(crypto.getRandomValues(new Uint8Array(32)), (n) =>
  n.toString(16).padStart(2, "0"),
).join("");

3. 创建 GitHub OAuth App#

这个应用让你和读者能够通过 GitHub 登录博客。

打开 GitHub Settings → Developer settings → OAuth Apps → New OAuth App,也可以直接打开 创建 OAuth App 页面。

表单项

填写内容

Application name

自己的博客名称,例如 Flare Stack Blog

Homepage URL

https://blog.example.com

Application description

可留空

Redirect URI / Authorization callback URL

https://blog.example.com/api/auth/callback/github

GitHub OAuth App 示例:博客主页与完整登录回调地址
GitHub OAuth App 示例:博客主页与完整登录回调地址

将示例域名换成自己的域名,回调地址末尾的 /api/auth/callback/github 保持不变,其余选项保留默认值。

点击 Register application。在应用详情页:

  1. 复制 Client ID,填入运行时清单的 GITHUB_CLIENT_ID。

  2. 点击 Generate a new client secret,按 GitHub 提示完成身份确认。

  3. 立即复制新生成的 Client secret,填入 GITHUB_CLIENT_SECRET;离开页面后可能无法再次查看完整值。

4. 创建 Cloudflare 资源#

打开 Cloudflare 控制台,选择托管域名的账号。下面四种资源各创建一个,名称可以自定。

资源

左侧菜单入口

示例名称

写入构建清单的内容

D1 数据库

Storage & databases → D1 SQLite Database

blog-db

ID → D1_DATABASE_ID

R2 存储桶

Storage & databases → R2 Object Storage

blog-media

名称 → BUCKET_NAME

Queue 队列

Compute → Queues

blog-queue

名称 → QUEUE_NAME

KV 命名空间

Storage & databases → Workers KV

blog-cache

ID → KV_NAMESPACE_ID

D1:存放文章和用户数据#

进入 D1 SQLite Database,点击 Create Database,填写名称,例如 blog-db。位置选项保留默认,点击 Create。

创建 D1 数据库:填写名称,位置保留默认
创建 D1 数据库:填写名称,位置保留默认

返回数据库列表,找到刚创建的数据库,在 UUID 一栏点击复制,将完整 ID 填入 D1_DATABASE_ID。也可以在数据库详情中查看 Database ID。

D1 数据库列表中的 UUID
D1 数据库列表中的 UUID

部署时会自动初始化数据库。

R2:存放图片等文件#

进入 R2 Object Storage,点击 Create bucket,填写名称,例如 blog-media。Location 保留 Automatic,Default Storage Class 保留 Standard,点击页面底部的 Create bucket。

R2 存储桶的名称填写示例
R2 存储桶的名称填写示例

把存储桶名称填入 BUCKET_NAME,其余设置保留默认值。

Queue:处理通知等异步任务#

进入 Compute → Queues,点击 Create Queue,填写名称,例如 blog-queue,再点击 Create。

创建队列:名称填写完成后记入 QUEUE_NAME
创建队列:名称填写完成后记入 QUEUE_NAME

把队列名称填入 QUEUE_NAME。

KV:存放缓存#

进入 Storage & databases → Workers KV,点击 Create Instance(部分界面显示 Create namespace),填写 Namespace name,例如 blog-cache,点击 Create。

返回列表,复制这一行 ID 列中的完整值,填入 KV_NAMESPACE_ID。

KV 命名空间列表中的 ID
KV 命名空间列表中的 ID

5. 可选:开启图片优化#

开启 Cloudflare Image Transformations(图片转换) 后,博客会按需要对图片进行缩放和压缩。

在 Cloudflare 账号侧栏打开 Images & Stream → Transformations(部分界面位于 Images 下),找到博客所属的根域名,例如 example.com,为该域名启用转换。

进入域名的转换设置,Sources 选择 This zone only,允许本域名及其子域名作为图片来源,点击 Save 保存修改。

已启用图片转换的域名设置,Sources 选择 This zone only
已启用图片转换的域名设置,Sources 选择 This zone only

域名列表显示 Enabled,或设置页显示 Disable for zone,即表示已启用。跳过此步骤时,博客使用原图。转换额度及价格见 Cloudflare Images 定价。

6. 创建 Worker 并部署#

连接自己的 Fork#

打开 Compute → Workers & Pages → Create application,选择 Continue with GitHub。

创建 Worker 应用,选择 Continue with GitHub
创建 Worker 应用,选择 Continue with GitHub

首次连接时,按页面提示授权 Cloudflare 访问你的 Fork 仓库。然后选择自己的 GitHub 账号,搜索 flare-stack-blog,选中仓库并点击 Next。

填写构建设置#

在 Set up your application 中,按下面填写:

设置项

填写内容

Project name / Worker name

与 WORKER_NAME 相同,例如 flare-blog

Build command

bun run build

Deploy command

bun run deploy

Path / Root directory

/,即仓库根目录

Builds for non-production branches

首次部署建议取消勾选

构建和部署命令的填写示例
构建和部署命令的填写示例

展开 Advanced settings,添加构建清单中的六个变量:Variable name 填等号左边的名称,Variable value 填等号右边的值,点击 Add variable 继续添加下一项。

构建变量示例:WORKER_NAME 的值必须与应用名称一致
构建变量示例:WORKER_NAME 的值必须与应用名称一致

可在这里额外添加 BUN_VERSION=1.3.5,指定构建环境使用的 Bun 版本。构建环境的 Node 版本由仓库根目录的 .node-version 指定,无需额外设置。

确认生产分支为 Fork 的 main。有些界面在创建时使用仓库默认分支,可在创建后的 Settings → Builds → Branch control / Production branch 中核对。后续自动部署监听的就是这个分支。

点击 Deploy,等待构建和部署成功。上述命令会自动完成资源绑定、数据库迁移和 Worker 发布,并通过 Custom Domain(自定义域) 绑定博客域名。

添加运行时变量#

第一次部署成功后,继续打开该 Worker 的 Settings → Runtime variables and secrets(部分界面显示 Variables and Secrets),点击 Add variable。

运行时变量弹窗:Key、Value、Secret 和保存部署按钮
运行时变量弹窗:Key、Value、Secret 和保存部署按钮

添加运行时清单中已填好的变量。可以逐项填写 Key / Value,也可以将 KEY=value 格式的变量行粘贴到 Key 输入框,批量导入。

  • 所有运行时变量都必须勾选 Secret(包括 BETTER_AUTH_URL、DOMAIN、GITHUB_CLIENT_ID、ENVIRONMENT)。部署程序会保留机密,但会在每次部署时丢弃没有写进配置文件的普通文本变量,导致博客报 Invalid environment variables。

  • ENVIRONMENT 使用第 2 步设置的 prod。

点击 Add variable and deploy(保存并部署),等待变量生效。

最后在 Worker 的 Domains(部分界面为 Settings → Domains & Routes)中确认自己的域名已绑定;DNS 和证书生效后,通过 https://blog.example.com 访问。

7. 登录博客,成为管理员#

打开自己的博客域名,点击右上角的登录入口,选择 GitHub 登录,完成 GitHub 授权。第一次登录会自动创建博客用户。

新数据库中第一个创建的用户会自动成为管理员。 配置好后先完成自己的首次登录,再把地址分享给别人。

登录后,点击右上角头像,应当能看到 管理后台;也可以直接访问 https://blog.example.com/admin。

管理员登录后可从头像菜单进入管理后台
管理员登录后可从头像菜单进入管理后台

进入后台后,可以设置博客名称、介绍和外观,上传一张图片并发布第一篇文章。GitHub 登录不依赖邮件配置;邮箱注册、找回密码和通知邮件需要之后在后台配置邮件发送服务。

8. 以后如何更新#

上游有新代码时,先阅读 更新说明,然后:

  1. 打开自己的 Fork 仓库,切换到 Cloudflare 监听的生产分支,本文为 main。

  2. 点击文件列表上方的 Sync fork → Update branch,将上游更新同步到自己的仓库。

  3. 打开 Cloudflare 对应 Worker 的 Deployments / Builds,等待这次提交的构建和部署成功。

  4. 刷新博客,检查首页和后台是否正常。

同步产生新提交后,Cloudflare Workers Builds 会自动部署,并执行数据库迁移,已有资源和运行时机密会保留。

从使用 wrangler.jsonc 的旧版本升级(v2.x → v3)时,同步之前请先完成两件事,否则第一次自动部署就会出问题:

  1. 打开 Worker 的 Settings → Runtime variables and secrets,把仍是普通文本的运行时变量(例如 BETTER_AUTH_URL、DOMAIN、GITHUB_CLIENT_ID、ENVIRONMENT)删除后以 Secret 类型重新添加。新版部署程序不再保留普通文本变量。

  2. 把 Build command 改为 bun run build。旧的 bun run wrangler:prepare && bun run build 在本版本仍可运行(wrangler:prepare 只会打印一条废弃提示),但之后的版本会移除它。

另外,Durable Object 的声明方式已改为 exports。部署成功后,无法再回退到旧的基于 migrations 的 Wrangler 配置,回退需要把 DO 同样声明在旧配置的 exports 里。

若更新说明要求新增变量或调整配置,请一并完成。自行修改过代码的仓库,可能需要先解决同步冲突。

可选配置#

先完成基本部署,再按需添加。所有变量的完整说明以 .env.example 和 .dev.vars.example 为准。

功能

构建时变量

运行时变量

补充说明

Turnstile 人机验证

VITE_TURNSTILE_SITE_KEY

TURNSTILE_SECRET_KEY(Secret)

在 Cloudflare 创建站点并添加博客域名;Site Key 与 Secret Key 成对使用

Umami 访问统计

VITE_UMAMI_WEBSITE_ID

UMAMI_WEBSITE_ID、UMAMI_SRC

两边 Website ID 填同一个,UMAMI_SRC 填服务地址,例如 https://cloud.umami.is

Umami 文章热度同步

同上

Cloud 使用 UMAMI_API_KEY;自托管使用 UMAMI_USERNAME、UMAMI_PASSWORD

API Key 和密码设为 Secret;两种认证方式二选一。API 地址可按模板配置 UMAMI_API_URL

后台更新检查改走 GitHub API

无

GITHUB_TOKEN(Secret)

不配也能检查更新:默认读取 GitHub 发布页的跳转。配了 token 会优先走 API,更稳定;API 失败时仍会退回发布页。按模板链接创建 Fine-grained token,权限保留默认的公共仓库只读访问

修改构建时变量后,需要重新触发构建,新值才会进入部署产物。修改运行时变量后,使用保存并部署使其生效。

常见问题#

构建失败,提示缺少变量或找不到资源#

打开失败记录的构建日志,先查看具体缺少哪一项,再检查 Settings → Builds 中的变量:

  • 六个构建必填项是否齐全,名称是否拼写正确,值前后是否混入空格。

  • D1 和 KV 填的是完整 ID,R2 和 Queue 填的是名称。

  • Worker 和资源是否位于同一 Cloudflare 账号,WORKER_NAME 是否与应用名一致。

  • Build command 是否为 bun run build,Deploy command 是否为 bun run deploy。

如果日志提示权限不足,检查 Builds 使用的 Cloudflare API token 是否有权部署 Worker、访问对应存储和队列资源、配置域名。构建授权说明见 Workers Builds 配置文档。修正后重新构建。

部署成功,但域名打不开或页面报错#

检查域名是否已在同一账号托管并处于 Active,Worker 的 Domains 中是否出现该域名,DNS 和证书是否已生效。如果选的子域名已有其他 DNS 记录或绑定,先确认冲突来源,或换一个空闲子域名。

如果已经能访问 Worker 但页面报错,检查五个运行时必填项是否已保存并部署,并到 Observability → Logs 查看错误。

GitHub 登录后提示回调地址错误,或回不到博客#

逐项对照,下面三个值中的域名必须一致:

纯文本
博客访问地址:                 https://blog.example.com
BETTER_AUTH_URL:             https://blog.example.com
GitHub OAuth Redirect URI:   https://blog.example.com/api/auth/callback/github

同时确认 Client ID 和 Client Secret 来自同一个 OAuth App,运行时 DOMAIN 是纯域名,并通过配置的博客域名登录。

登录了,但没有管理员权限#

管理员判断依据是数据库里的第一个用户。如果复用了已有用户的数据库,请使用原来的管理员账号登录。

同步了 Fork,但没有自动部署#

检查更新是否进入 Cloudflare 监听的生产分支,以及 Settings → Builds 中的 GitHub 连接、生产分支和自动构建设置。如果配置了 Build watch paths,还要检查本次改动是否被排除。没有新提交,或仅同步到其他分支,都不会触发生产分支部署。

图片能显示,但没有优化效果#

确认博客所属域名的 Transformations 已启用,Sources 允许博客域名及其子域名,并且转换额度可用。本地环境、GIF、原图请求不会转换,转换失败也会回退原图。应使用博客公开页面中请求了宽度或质量参数的图片检查效果。

END