Files
xbin/README.zh.md
T

13 KiB
Raw Blame History

Xbin

English

Codecov CI CodeQL Deploy

Xbin 是一个构建在 Cloudflare Workers 之上的、类似 PrivateBin 的端到端加密 Pastebin。它包含一个用于创建和读取加密内容的浏览器应用、一个现代 JSON API,以及一个兼容旧版 PrivateBin 的接口层,方便迁移和互操作。

所有内容都会先在浏览器中完成加密,再上传到服务端。Worker 仅将加密后的载荷存储到 R2,将生命周期元数据存储到 D1,并借助 Durable Objects 与 Queues 处理阅后即焚声明和后台清理任务。

特性亮点

  • 浏览器端加密,分享密钥通过 URL fragment 传递
  • 支持可选密码、过期时间、阅后即焚链接,以及每条内容独立的删除令牌
  • 支持纯文本、代码高亮和 Markdown 渲染
  • 支持加密附件上传、下载与预览
  • 支持兼容粘贴内容的讨论线程
  • 提供位于 /api/v1/* 的现代 REST API
  • 支持兼容旧版 PrivateBin 的 API,以及文件系统导入工具
  • 原生运行在 Cloudflare 平台之上,使用 Workers、D1、R2、Durable Objects、Queues 和定时清理

安全模型

  1. 浏览器生成随机密钥,并在上传前完成内容加密。
  2. Worker 仅在 R2 中保存加密信封,在 D1 中保存元数据。
  3. 分享链接通过查询参数携带 paste id,通过 URL fragment 携带解密密钥,例如 https://paste.example.com/?abcdef1234567890#secretKey。fragment 不会发送给服务器。
  4. 如果设置了可选密码,客户端会在解密前使用 PBKDF2 将密码与 fragment 密钥组合。
  5. 任何拿到完整分享 URL 的人都可以解密内容。删除令牌与分享链接分离,且仅在创建或导入 paste 时返回。

架构

组件 职责
Cloudflare Worker HTTP API、静态资源分发、SEO 元数据重写、配置接口和导入鉴权
Durable Object 串行化处理阅后即焚的声明与消费操作
D1 Paste 和评论的元数据、生命周期状态、删除令牌哈希、焚毁声明
R2 加密后的 paste 与评论载荷 blob
Queue 异步清理已过期、已删除和已焚毁的内容
Cron trigger 每分钟释放过期的焚毁声明并扫描已过期的 paste
assets/ SPA 在浏览器中完成加密、解密、渲染和分享

快速开始

前置条件

  • Bun
  • 一个可使用 Workers、D1、R2、Queues 和 Durable Objects 的 Cloudflare 账号
  • 如果你计划在本机部署,需要本地已完成 Wrangler 登录认证

安装依赖

bun install

创建 Cloudflare 资源

首次部署前,请先创建你自己的资源,然后将 wrangler.jsonc 中的名称和 ID 替换为你账号下的值。

bunx wrangler d1 create xbin
bunx wrangler r2 bucket create xbin-pastes
bunx wrangler queues create xbin-gc

说明:

  • 当前存储库中的 wrangler.jsonc 已包含具体的 D1 和 R2 标识符。如果你要 fork 或部署自己的实例,请务必替换成你自己账号中的值。
  • 你只需要手动创建 D1、R2 和 Queue。Durable Object 绑定以及对应的 SQLite 类已经在 wrangler.jsonc 中声明,会在部署和迁移时自动创建。
  • 当前存储库设置了 workers_dev = false。部署你自己的 fork 前,请先在 wrangler.jsonc 中配置自己的路由或自定义域名,或者将其改为 workers_dev = true,这样应用才会有可访问的主机名。
  • 变更绑定或环境变量后,请重新生成 Worker 类型:
bun run cf-typegen

配置本地密钥

将 .dev.vars.example 复制为 .dev.vars,并填写你要使用的可选密钥:

Copy-Item .dev.vars.example .dev.vars

可用密钥:

  • TURNSTILE_SITE_KEY
  • TURNSTILE_SECRET_KEY
  • IMPORT_TOKEN

大多数非敏感的运行时默认值都位于 wrangler.jsonc 的 vars 段中。

本地运行

bun run dev

Wrangler 会通过同一个 Worker 入口同时提供 SPA 和 API。

通过 GitHub Actions 部署

默认的部署路径是 GitHub Actions。如果你要部署自己的实例,建议从 xixu-me/xbin fork 开始。

发布流程如下:

  1. 在你的 fork 中,把 CLOUDFLARE_ACCOUNT_ID 和 CLOUDFLARE_API_TOKEN 配置为 GitHub Actions secrets。
  2. 向你 fork 的 main 分支推送代码。
  3. CI 会运行格式检查、类型检查、Wrangler 类型校验、带覆盖率的测试,以及 Wrangler 部署 dry run。
  4. 如果该次 main 推送通过了 CI,Deploy 会发布通过校验的同一份提交。

Pull Request 同样会运行 CI,但不会自动部署。你也可以在自己的 fork 中通过 workflow_dispatch 手动触发部署流程。

部署工作流最终执行的是:

bunx wrangler deploy --keep-vars --message "GitHub Actions deploy for ${GITHUB_SHA}"

--keep-vars 表示除非你有意在 Cloudflare 或部署配置中修改,否则远端 Worker 变量会被保留。

本地手动部署

如果你需要绕过 GitHub Actions,在本地直接部署:

bun run deploy

常用命令

命令 用途
bun run dev 使用 Wrangler 在本地运行 Worker
bun run start 本地 Wrangler 开发的别名
bun run check 对 TypeScript 代码库执行类型检查
bun run test 使用 Vitest 运行 Worker 集成测试
bun run test:coverage 运行测试并输出 Istanbul 覆盖率报告
bun run format 使用 Prettier 格式化整个存储库
bun run format:check 检查格式但不修改文件
bun run cf-typegen 在配置变化后刷新 Worker 绑定类型
bun run deploy 发布 Worker

配置项

变量 默认值 用途
XBIN_APP_NAME Xbin UI 和元数据中显示的品牌名
XBIN_APP_VERSION 1.0.0 在应用配置接口和页脚中暴露的版本号
XBIN_PROJECT_PAGE_URL https://github.com/xixu-me/xbin UI 中显示的项目链接
XBIN_BASE_PATH / 用于构建分享链接、规范 URL 和站点地图链接的挂载路径
XBIN_MAX_PASTE_BYTES 10000000 加密 paste 载荷的最大字节数
XBIN_DEFAULT_EXPIRATION 1hour UI 和 API 使用的默认过期键
XBIN_SUPPORTED_EXPIRATIONS 5min,10min,30min,1hour,3hour,6hour,12hour,1day,3day,1week 应用暴露的过期键列表,逗号分隔
XBIN_ENABLE_LEGACY_API true 是否启用兼容 PrivateBin 的旧版 JSON API
XBIN_REQUIRE_TURNSTILE false 是否要求在创建 paste 和评论时传入 turnstileToken
XBIN_BURN_CLAIM_TTL_SECONDS 120 阅后即焚声明在释放前可保留的秒数
TURNSTILE_SITE_KEY 未设置 启用 Turnstile 时暴露给客户端的站点密钥
TURNSTILE_SECRET_KEY 未设置 Worker 用于校验 Turnstile 令牌的密钥
IMPORT_TOKEN 未设置 启用并保护 PrivateBin 导入接口

配置解析器还支持 1month、1year 和 never 这些过期键,只要你愿意将它们暴露给客户端即可。

API 概览

写入 API 接收的是经过加密的、PrivateBin 风格的信封对象,而不是明文内容。一个最小创建请求示例如下:

{
	"v": 2,
	"adata": [["iv", "salt", 100000, 256, 128, "aes", "gcm", "none"], "plaintext", 0, 0],
	"ct": "ciphertext",
	"meta": { "expire": "1day" }
}

核心接口:

方法 路径 用途
GET /api/v1/config 返回运行时 UI 和功能配置
POST /api/v1/pastes 创建 paste,并返回 { id, shareUrl, deleteToken }
GET /api/v1/pastes/:id 返回加密 paste 信封和评论
DELETE /api/v1/pastes/:id 在提供 { "deleteToken": "..." } 时删除 paste
POST /api/v1/pastes/:id/comments 为启用讨论的 paste 创建评论
POST /api/v1/pastes/:id/consume 使用 { "claimToken": "..." } 完成一次阅后即焚读取
POST /api/v1/admin/import/privatebin 在授权后导入 PrivateBin 文件系统数据

说明:

  • 对于阅后即焚的 paste,GET /api/v1/pastes/:id 会返回一个 claimToken。客户端在成功解密后必须继续调用 /consume。
  • 启用 Turnstile 后,在创建 paste 和创建评论的请求体中都需要包含 turnstileToken。
  • 阅后即焚 paste 不支持评论。

PrivateBin 兼容性与导入

Xbin 提供两种兼容路径:

  • 通过 X-Requested-With: JSONHttpRequest 识别旧版 JSON API 调用。
  • 对于 /api/v1/pastes?<pasteId> 这类旧版浏览器分享 URL,返回 SPA 外壳页面,让客户端在本地恢复分享内容。

如果要从 PrivateBin 的文件系统导出中导入数据,先为 Worker 设置 IMPORT_TOKEN,然后执行:

bun run import:privatebin:fs -- --source /path/to/privatebin/data --base-url https://paste.example.com --token your-import-token --report ./import-report.json

导入器会:

  • 遍历 *.php paste 文件及其相邻的 .discussion/ 目录
  • 在可用时保留创建时间和过期时间元数据
  • 跳过已经过期的 paste
  • 为每条导入后的 paste 返回一个新的 deleteToken,因为 Xbin 会在导入时重新生成删除凭证

存储库结构

路径 用途
src/index.ts Worker 入口,负责 HTTP 路由、静态资源分发、定时清理和队列处理
src/lib/ 配置解析、校验、数据访问、Schema 和共享类型
assets/ 浏览器应用、HTML 外壳、CSS 和 vendored 客户端库
scripts/ 一次性工具,例如 PrivateBin 文件系统导入器
migrations/ D1 Schema 迁移
test/ Worker 集成测试和仓储层测试

测试与质量

本存储库使用带 Cloudflare Workers 运行池的 Vitest、TypeScript 类型检查、Wrangler 类型校验和 Prettier 格式化。CI 还会在允许生产部署前执行一次 Wrangler 部署 dry run。Codecov 配置了 95% 的项目覆盖率和 90% 的补丁覆盖率目标,因此除文档外,代码改动通常都应附带测试。

与主要 CI 质量门槛一致的一组本地校验命令如下:

bun run format:check
bun run check
bunx wrangler types --check
bun run test:coverage

相关文档

许可证

本项目基于 GNU Affero General Public License v3.0 发布。完整条款请参见 LICENSE。