-- 0% read
阅读地图

    Cloudflare Wrangler 实战:工具站的部署与维护

    2026-06-02 · #cloudflare #wrangler #workers #email #pastebin #image-hosting #self-hosted

    这篇笔记整理我用 Cloudflare Wrangler 部署和维护三个二级域名工具站的过程: mail.5imcs.compaste.5imcs.comimg.5imcs.com。 重点不是罗列命令,而是建立一套可复用的操作模型:本地项目、wrangler.toml、Cloudflare 资源绑定、自定义域名、部署版本和运行日志之间要保持一致。

    其中 mail.5imcs.compaste.5imcs.com 是两个完整案例; img.5imcs.com 暂作为图床入口记录。

    二级域名入口

    从 Notes & Logs 进入此页后,可直接跳转到常用工具站点。

    Cloud Mail

    mail.5imcs.com

    域名邮箱与收信服务,基于 Cloudflare Workers、D1、KV、R2、Email Routing 和前端静态资源部署。 来源:maillab/cloud-mail

    打开 Mail

    Pastebin Worker

    paste.5imcs.com

    文本、代码片段、短链接和较大内容的分享工具,使用 Worker API、静态前端、KV、R2 和 Cron。 来源:SharzyL/pastebin-worker

    打开 Paste

    CloudFlare ImgBed

    img.5imcs.com

    图床与文件托管入口,用于图片上传、对象存储和外链访问。 来源:MarSeventh/CloudFlare-ImgBed

    打开 ImgBed

    1. 先把 Wrangler 想清楚

    Wrangler 是 Cloudflare Workers 的本地命令行工具。通过它可以完成登录、构建、dry-run、部署、查看日志、创建 KV/R2/D1 资源、绑定静态资源、配置 Cron、管理版本和回滚等操作。

    我现在更倾向于把它理解成 Workers 的“部署控制台”:

    最容易误解的一点是:Wrangler 不只是“上传代码”。如果代码里写了 env.PB.get(...),那么 PB 必须在 wrangler.toml 里绑定到一个 KV namespace;如果代码里写了 env.R2.put(...)R2 必须绑定到一个 R2 bucket。binding 名称是运行时变量名,不是资源展示名。

    2. 安装、登录与基本命令

    Cloudflare 官方更推荐在项目中本地安装 Wrangler,而不是长期依赖全局安装。这样每个项目可以使用自己的 Wrangler 版本,项目脚本也更容易复现。

    npx wrangler <command>
    pnpm wrangler <command>
    yarn wrangler <command>

    在使用 pnpm 的项目里,我通常先确认版本和登录状态:

    pnpm wrangler --version
    pnpm wrangler whoami

    如果尚未登录,运行:

    pnpm wrangler login

    该命令会打开浏览器完成 Cloudflare 授权。授权后,本地 Wrangler 才能创建资源、部署 Worker、查看日志和执行回滚。

    常用命令可以先记住这一组:

    pnpm wrangler --version
    pnpm wrangler whoami
    pnpm wrangler deploy --dry-run
    pnpm wrangler deploy
    pnpm wrangler tail

    如果项目已经在 package.json 里定义了脚本,应优先使用项目脚本。例如:

    {
      "scripts": {
        "deploy": "wrangler deploy",
        "build": "wrangler deploy --dry-run --outdir=dist"
      }
    }

    对应命令为:

    pnpm run build
    pnpm run deploy

    3. 读懂 wrangler.toml

    wrangler.toml 是 Worker 的部署说明书。它把代码入口、运行时、域名、资源绑定和环境变量放在同一个配置文件中。一个最小结构如下:

    name = "my-worker"
    main = "src/index.ts"
    compatibility_date = "2026-06-02"
    workers_dev = true
    
    [[routes]]
    pattern = "example.com"
    custom_domain = true
    
    [[kv_namespaces]]
    binding = "MY_KV"
    id = "<kv_namespace_id>"
    
    [[r2_buckets]]
    binding = "MY_R2"
    bucket_name = "my-r2-bucket"
    
    [vars]
    PUBLIC_SETTING = "not-secret"
    字段 作用
    name Cloudflare 里的 Worker 名称。
    main Worker 入口文件,常见形式是 src/index.tssrc/index.jsworker/index.ts
    compatibility_date Workers 运行时兼容日期。它不是部署日期,而是决定启用哪些运行时行为。
    workers_dev 是否启用 *.workers.dev 访问入口。
    routes 绑定自定义域名或路由。custom_domain = true 表示直接把 Worker 挂到该域名。
    kv_namespaces 把 Cloudflare KV namespace 绑定给 Worker。
    r2_buckets 把 R2 bucket 绑定给 Worker。
    d1_databases 把 D1 数据库绑定给 Worker。
    assets 上传并绑定静态前端目录。
    triggers 声明 Cron 定时触发器。
    vars 普通环境变量,适合保存非敏感配置。

    binding 是什么

    binding 是代码里的变量名,不是 Cloudflare 资源名。例如:

    [[kv_namespaces]]
    binding = "PB"
    id = "<kv_namespace_id>"

    这表示 Worker 代码里可以这样访问 KV:

    await env.PB.get("some-key")

    如果把配置改成 binding = "PASTE_KV",而代码仍然读取 env.PB,部署可能通过,但运行时会报错。 所以配置资源时应先搜索代码中的 env.,再决定 binding 名称。

    vars 与 secrets 的区别

    [vars] 会写进配置文件,适合公开 URL、标题、开关、默认过期时间等非敏感值。敏感值应使用 Wrangler secret:

    pnpm wrangler secret put JWT_SECRET
    pnpm wrangler secret put API_TOKEN

    这样 secret 不会出现在 wrangler.toml 中。如果某个项目已经把敏感值写入配置文件,后续应逐步迁移到 secret,并避免提交到公开仓库。

    4. dry-run、部署与回滚

    正式部署前先运行:

    pnpm wrangler deploy --dry-run

    dry-run 会构建、打包并检查配置,但不会把当前版本切到线上。重点看这些输出:

    带输出目录的 dry-run 常用于检查打包产物:

    pnpm wrangler deploy --dry-run --outdir=dist

    正式部署:

    pnpm wrangler deploy

    部署后立刻做三类检查:

    pnpm wrangler tail
    curl -I https://your-domain.example
    curl https://your-domain.example/some-health-or-home-page

    如果线上出现问题,优先考虑回滚 Worker 代码版本:

    pnpm wrangler deployments
    pnpm wrangler rollback
    pnpm wrangler rollback <version_id>

    回滚只处理 Worker 代码版本,不会自动回滚 D1、KV、R2 中的数据。如果新版本改了数据库结构或对象格式,回滚前要判断旧代码是否还能读取新数据。

    5. Cloudflare 常用资源速查

    Custom Domain

    把 Worker 挂到自己的域名上:

    [[routes]]
    pattern = "paste.5imcs.com"
    custom_domain = true

    也可以写成数组形式:

    routes = [
      { pattern = "mail.5imcs.com", custom_domain = true }
    ]

    部署后 Cloudflare 会处理路由和证书。刚绑定后如果短时间内 SSL 异常,先等待证书和边缘网络传播,再检查 Dashboard 状态。

    KV

    KV 适合保存小数据、元数据、配置和短文本。创建 namespace:

    pnpm wrangler kv namespace create PB

    绑定示例:

    [[kv_namespaces]]
    binding = "PB"
    id = "<kv_namespace_id>"

    KV 是全球分布式读优化存储,写入和列表结果可能存在短暂延迟。删除验证时,不要只看 list,也要直接访问具体 key 或业务 URL。

    R2

    R2 适合保存附件、大 paste、图片和二进制对象。创建 bucket:

    pnpm wrangler r2 bucket create my-bucket

    绑定示例:

    [[r2_buckets]]
    binding = "R2"
    bucket_name = "my-bucket"

    R2 bucket 默认不是公开网站。Worker 通过 binding 访问对象,再由 Worker 决定是否把内容返回给用户。

    D1

    D1 是 Cloudflare 的 serverless SQL 数据库。创建数据库:

    pnpm wrangler d1 create cloud-mail-db

    绑定示例:

    [[d1_databases]]
    binding = "db"
    database_name = "cloud-mail-db"
    database_id = "<d1_database_id>"

    初始化或执行 SQL 通常使用:

    pnpm wrangler d1 execute cloud-mail-db --remote --file ./schema.sql

    具体 SQL 文件名要以项目实际迁移脚本为准。

    Static Assets

    如果 Worker 同时服务前端页面,可以配置:

    [assets]
    directory = "./dist"
    binding = "ASSETS"
    not_found_handling = "single-page-application"
    run_worker_first = true

    Cron Triggers

    Cron 用于定时执行 Worker 的 scheduled handler:

    [triggers]
    crons = ["0 0 * * *"]

    要禁用 Cron,应明确设为空数组:

    [triggers]
    crons = []

    只注释配置不一定能禁用已经部署的定时任务。

    6. 案例一:mail.5imcs.com / Cloud Mail

    mail.5imcs.com 来源于 maillab/cloud-mail。上游项目定位为基于 Cloudflare 的邮箱服务,支持用一个域名创建多个邮箱,并依赖 Workers、D1、KV、R2、Workers AI、Vue 和 Hono 等组件。

    这个项目可以理解为 Worker 后端加 Vue 前端。核心配置结构如下,已去掉本地路径和资源 ID:

    name = "cloud-mail"
    main = "src/index.js"
    compatibility_date = "2025-06-04"
    keep_vars = true
    workers_dev = true
    
    routes = [
      { pattern = "mail.5imcs.com", custom_domain = true }
    ]
    
    [[d1_databases]]
    binding = "db"
    database_name = "cloud-mail-db"
    database_id = "<d1_database_id>"
    
    [[kv_namespaces]]
    binding = "kv"
    id = "<kv_namespace_id>"
    
    [[r2_buckets]]
    binding = "r2"
    bucket_name = "cloud-mail-r2"
    
    [ai]
    binding = "ai"
    
    [assets]
    binding = "assets"
    directory = "./dist"
    not_found_handling = "single-page-application"
    run_worker_first = true
    
    [triggers]
    crons = ["*/30 * * * *", "0 16 * * *"]
    
    [vars]
    orm_log = false
    domain = ["5imcs.com"]
    admin = "<admin_email>"
    # JWT secret should be configured with wrangler secret put, not stored here.
    
    [build]
    command = "pnpm --prefix ../mail-vue install && pnpm --prefix ../mail-vue run build"

    这里最关键的是 binding 名称:

    资源 binding 说明
    D1 db 保存邮箱和邮件相关结构化数据。
    KV kv 保存轻量状态、缓存或配置。
    R2 r2 保存附件或较大对象。
    Static Assets assets 托管 Vue 前端构建产物。
    Workers AI ai 项目中的 AI binding。

    推荐部署流程:

    # 在 cloud-mail 的 Worker 项目目录中运行
    pnpm install
    pnpm wrangler whoami
    pnpm wrangler deploy --dry-run
    pnpm wrangler deploy

    如果前端依赖构建脚本被 pnpm 拦截,应按 pnpm 提示批准必要 build scripts,再重新 dry-run。部署后检查:

    curl -I https://mail.5imcs.com/
    pnpm wrangler tail

    数据库初始化要按项目提供的初始化入口或 SQL 执行。新环境至少要确认:

    Email Routing 接入思路:

    1. 在 Cloudflare 的 5imcs.com 中启用 Email Routing。
    2. 创建或确认目标 Worker:cloud-mail
    3. 把 catch-all 路由到 Worker。
    4. 注意显式地址规则优先于 catch-all,例如显式管理员地址转发规则会先于 catch-all 生效。
    5. 发测试邮件,观察 Worker 日志和 Cloudflare Email Routing 状态。

    7. 案例二:paste.5imcs.com / Pastebin Worker

    paste.5imcs.com 来源于 SharzyL/pastebin-worker。上游项目是运行在 Cloudflare Workers 上的 pastebin,支持短链接、自定义链接、语法高亮、客户端加密、Markdown 渲染、URL shortener、HTTP API 和 CLI。

    这个项目是 Worker API 加 React/Vite 前端。核心配置结构如下,已去掉资源 ID 和认证 hash:

    name = "pastebin-worker"
    compatibility_date = "2025-04-24"
    workers_dev = false
    main = "worker/index.ts"
    
    [assets]
    directory = "dist/frontend"
    run_worker_first = true
    binding = "ASSETS"
    
    [triggers]
    crons = ["0 0 * * *"]
    
    [[routes]]
    pattern = "paste.5imcs.com"
    custom_domain = true
    
    [[kv_namespaces]]
    binding = "PB"
    id = "<kv_namespace_id>"
    
    [[r2_buckets]]
    binding = "R2"
    bucket_name = "pastebin-worker-r2"
    
    [vars]
    DEPLOY_URL = "https://paste.5imcs.com"
    INDEX_PAGE_TITLE = "5imcs Pastebin"
    BASIC_AUTH = { admin = "<bcrypt_hash>" }
    R2_THRESHOLD = "20K"
    R2_MAX_ALLOWED = "256M"
    DEFAULT_EXPIRATION = "7d"
    MAX_EXPIRATION = "90d"

    这个配置里需要重点确认:

    推荐部署流程:

    # 在 pastebin-worker 项目目录中运行
    pnpm install
    pnpm run build:frontend
    pnpm run typecheck
    pnpm run lint
    pnpm test
    pnpm wrangler deploy --dry-run --outdir=dist
    pnpm wrangler deploy

    如果只想按项目脚本做 dry-run:

    pnpm run build

    部署后检查:

    curl -I https://paste.5imcs.com/
    curl -I https://paste.5imcs.com/admin/history
    pnpm wrangler tail

    历史页应保持 Basic Auth 保护;匿名访问返回 401 是正常结果。上传类服务还要持续关注大小限制、默认过期时间、最大过期时间和 Cron 清理状态。

    8. img.5imcs.com / CloudFlare ImgBed

    img.5imcs.com 来源于 MarSeventh/CloudFlare-ImgBed。它承担图床和文件托管入口的角色,用于图片上传、对象存储和外链访问。

    这篇笔记暂不展开它的完整部署过程。就站点组织而言,它和 mail、paste 构成一个小型个人工具集:邮箱收发、文本分享、图片托管分别由三个二级域名承载。后续如果图床的存储后端、访问权限或管理策略调整,应单独补充部署细节。

    9. 日常运维清单

    每次改配置或改代码,建议按这个顺序:

    git status
    pnpm install
    pnpm run build
    pnpm run test
    pnpm wrangler deploy --dry-run
    pnpm wrangler deploy
    pnpm wrangler tail

    同时检查:

    10. 常见错误

    binding 名字改错

    现象:部署成功,但访问时报 Cannot read properties of undefined,或某个 env.X 不存在。 处理方式是回到代码里搜索 env.,确认 wrangler.toml 的 binding 名称一致。

    dry-run 构建失败

    wrangler deploy --dry-run 如果卡在 build command 或前端构建,应先单独跑前端构建命令:

    pnpm --prefix ../mail-vue run build
    pnpm run build:frontend

    等前端构建通过后,再回到 Wrangler dry-run。

    自定义域名刚部署后 SSL 异常

    如果 curl 或浏览器提示 SSL 连接问题,先等几分钟,再检查 Cloudflare Dashboard 中 Worker route、custom domain 和证书状态。

    KV 删除后列表里还看得到

    KV 有最终一致性特征,列表结果可能短时间滞后。验证删除时,应直接请求业务 URL 或具体 key,不要只依赖 list。

    Basic Auth 配置后没有生效

    按顺序检查:

    11. 安全建议

    12. 参考