banner
约 1,800 字
6 分钟

PocketChest 部署教程:Cloudflare 搭一个「取件码」式临时文件分享站

PocketChest 部署教程:Cloudflare 搭一个「取件码」式临时文件分享站

摘要

PocketChest 用 Workers + D1 + R2 搭免注册文件分享站:6 位取件码、200GB 分片上传、自动过期与可选 TOTP。含建库建桶、部署与排错。

PocketChest 部署教程:Cloudflare 搭一个「取件码」式临时文件分享站

给朋友传个 4GB 的镜像包,网盘要登录、要装客户端、还限速;微信传不上去;一次性网盘又怕文件躺在别人服务器上。PocketChest 的思路很直白——上传后给你一个 6 位取件码,像快递柜一样,对方拿到码就能取,到期自动销毁

仓库地址:Hzao/PocketChest(MIT)。完整部署细节以仓库的 DEPLOYMENT.md 为准,本文是把它读薄后的实操版。

PocketChest 首页:左侧 Share Files 上传,右侧 Retrieve Files 用取件码取件
PocketChest 首页:左侧 Share Files 上传,右侧 Retrieve Files 用取件码取件

一、它是什么,为什么值得自建

一个 chest(文件包)就是你一次上传的一批文件和文本,服务端给你一个 ABC123 这样的 6 位码。核心能力:

  • 免注册:没有账号体系,上传即用

  • 大文件:走 R2 分片上传,单个文件最大 200GB

  • 自动过期:1 / 3 / 7 / 15 天可选,也可以设永久

  • 可选 TOTP:开启后只有持验证码的人能上传,适合团队内部用

  • 每小时自动清理:定时任务删除过期会话、24 小时以上的未完成上传,以及对应的 R2 对象

架构上前后端分离:

技术

部署位置

后端

Cloudflare Worker + D1 + R2

Workers

前端

Next.js 14 + Tailwind

Cloudflare Pages

语言

TypeScript

二、前置条件

  • Cloudflare 账号(免费层可用),并且有一个托管在 Cloudflare 的域名

  • 本机装好 Wrangler CLI:

bash
npm install -g wrangler
wrangler login
  • Node.js 环境(跑 npm 与脚本)

三、第一步:拉代码、填两份配置模板

官方把配置做成了模板,先复制出来(wrangler.jsonc.env.local 都不该进 Git):

bash
git clone https://github.com/Hzao/PocketChest.git
cd PocketChest

cp pocket-chest-backend/wrangler.jsonc.template pocket-chest-backend/wrangler.jsonc
cp pocket-chest-frontend/.env.local.template pocket-chest-frontend/.env.local

四、第二步:建 D1 与 R2 并回填配置

bash
cd pocket-chest-backend
wrangler d1 create pocket-chest
wrangler r2 bucket create pocket-chest

d1 create 输出的 database_id 填进 pocket-chest-backend/wrangler.jsonc

jsonc
{
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "pocket-chest",
      "database_id": "<你的 database-id>"
    }
  ]
}

R2 绑定默认就对,除非你换了桶名:

jsonc
{
  "r2_buckets": [
    {
      "bucket_name": "pocket-chest",
      "binding": "R2_STORAGE"
    }
  ]
}

binding 字段名必须保持 DBR2_STORAGE,改名代码就找不到资源了。

然后初始化表结构:

bash
wrangler d1 execute pocket-chest --file=src/schema.sql --remote

五、第三步:生成本地能跑起来的环境

后端:

bash
npm install
npm run dev     # http://localhost:8787

前端另开一个终端:

bash
cd ../pocket-chest-frontend
npm install
npm run dev     # http://localhost:3000

前端通过 .env.local 里的 NEXT_PUBLIC_API_URL 找后端。本地调试时把它指向 http://localhost:8787 即可。先在这里把上传 → 取件跑通,再去部署,能省掉一半排错时间。

六、第四步:配置密钥与 TOTP

1. 用官方脚本生成密钥

bash
cd pocket-chest-backend/scripts

# 只生成 JWT + 一个 TOTP 用户
node generate-secrets.js admin

# 生成 JWT + 多个 TOTP 用户
node generate-secrets.js admin user1 user2

# 只想追加 TOTP 用户
node generate-secrets.js --totp-only newuser1

脚本会输出 JWT_SECRET 以及每个用户的 otpauth:// 链接,后者直接扫进 1Password / Google Authenticator 就行。

2. 决定要不要开 TOTP

pocket-chest-backend/wrangler.jsonc 里控制:

jsonc
{
  "vars": {
    "REQUIRE_TOTP": "true"
  }
}
  • 团队内部用 → "true",只有持码的人能上传

  • 公开分享用 → "false",任何人拿到前端地址就能上传

3. 写入 Cloudflare Secrets

密钥绝不能写进 wrangler.jsonc 的 vars 段

bash
cd ..    # 回到 pocket-chest-backend
wrangler secret put JWT_SECRET
wrangler secret put TOTP_SECRETS   # 仅当 REQUIRE_TOTP 为 true

被问「是否创建同名 Worker 并写入密钥」时选 Y

⚠️ Worker 的 Secret 是加密且不可回读的。以后要加 TOTP 用户,最省事的做法是重新生成全部用户的密钥,再整体 wrangler secret put TOTP_SECRETS,然后让每个人重新录入——比手工拼接旧密钥靠谱。

七、第五步:部署后端 Worker

bash
npm install
wrangler deploy

清理用的 Cron 任务写在 wrangler.jsonc 里,会跟着一起部署,不用手动配。

绑自定义域名(国内访问必需)

默认的 *.workers.dev 在国内打不开,所以自定义域名不是可选项。直接在 wrangler.jsonc 里写路由:

jsonc
{
  "routes": [
    {
      "pattern": "api-pc.yourdomain.com",
      "custom_domain": true
    }
  ],
  "workers_dev": false
}

三个容易踩的点:

  1. 不要提前手工加 DNS 记录,Cloudflare 部署时会自己创建

  2. 用三级域名api.yourdomain.com)才能自动签发 SSL;四级及以上(api.pc.yourdomain.com)拿不到证书

  3. workers_dev: false 可以关掉 workers.dev 域名,生产环境建议关

八、第六步:部署前端到 Cloudflare Pages

先把 .env.local 里的后端地址改成真实地址:

bash
NEXT_PUBLIC_API_URL=https://api-pc.yourdomain.com

然后构建并部署:

bash
cd pocket-chest-frontend
npm install
npm run build
npx wrangler pages deploy out --project-name your-unique-project-name

--project-name全局唯一的,太大众的名字会撞车,加个前缀更稳。也可以用 Git 集成方式接入,参考官方 Pages Git 集成文档

最后到 Cloudflare Dashboard → Pages → 你的项目 → Custom domains 给前端也绑上域名,等证书签发完成(通常几分钟)。

九、验证

  1. 打开前端域名,点 Start Sharing(开了 TOTP 会先弹验证框)

  2. 传一个小文件,拿到 6 位取件码

  3. 换一个浏览器/无痕窗口,用取件码取回,确认能下载

  4. 传一个大于 100MB 的文件,确认分片上传没断(这是 R2 分片路径,最值得单独验一次)

十、常见问题排查

现象

可能原因

处理

上传报跨域错误

后端 Access-Control-Allow-Origin 没放行前端域名

检查后端 CORS 配置

接口报数据库错误

D1 没绑定或 binding 名不对

确认 wrangler.jsoncbindingDB

上传/下载失败

R2 桶不存在或 binding 名不对

桶要在,且 bindingR2_STORAGE

TOTP 一直验证不过

密钥格式不对或手机时间不同步

检查 secret 是否完整粘贴,校准设备时间

国内访问不了

用的还是 *.workers.dev

绑三级自定义域名

想加人但看不到旧密钥

Secret 不可回读

重新生成全部用户的 TOTP 密钥后整体覆盖

表不存在

没跑 schema 初始化

重跑 wrangler d1 execute ... --file=src/schema.sql --remote

日常排错命令:

bash
wrangler tail                                                    # 看实时日志
wrangler d1 execute pocket-chest --command "SELECT COUNT(*) FROM sessions;" --remote

十一、免费额度与适用边界

资源

免费层

说明

D1

10 万读 / 5 万写 / 天

只有元数据,个人用量绰绰有余

R2

前 10GB 存储免费

之后约 $0.015/GB/月,出站流量免费

Workers

10 万请求 / 天

之后约 $0.5/百万

Pages

静态请求不限

函数调用 2 万次/月

它适合做「带过期的临时中转站」,不适合当长期网盘。 大文件分发也别指望它长期扛流量——过期时间设短一点,既安全也省钱。

写在最后

PocketChest 最聪明的地方是去掉了账号体系:没有注册、没有密码、没有找回,只有一个取件码和一条过期时间。这在「传完就完」的场景里,比任何网盘都干净。

自建它的真正理由不是省那点会员费,而是——文件始终躺在你自己的 R2 桶里,到期那一刻是真的被删掉,而不是「服务商说会删」。

END