From f868de3ba3214aa7da09d8f96cd57196a908f614 Mon Sep 17 00:00:00 2001 From: jinkunsun Date: Sun, 20 Sep 2026 00:59:15 +0800 Subject: [PATCH] docs: keep self-hosted deployment the default --- README.md | 28 +++++++++++++++++++++----- README.zh-CN.md | 28 +++++++++++++++++++++----- docs/deployment-modes.md | 43 ++++++++++++++++++++++++++++++++++++++++ docs/hosted.md | 2 ++ package.json | 4 ++-- src/about.ts | 7 +++++-- src/gallery/page.ts | 3 ++- src/hosted/ui.ts | 2 +- 8 files changed, 101 insertions(+), 16 deletions(-) create mode 100644 docs/deployment-modes.md diff --git a/README.md b/README.md index 1b3e8d9..da24bec 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,18 @@ Your own cross-device image & text pool, deployable to Cloudflare's free tier in **Product overview & setup guide:** https://shotsync-demo.defiabell.workers.dev/about +## Choose how to use ShotSync + +**Self-hosting is the default: no ShotSync account, Supabase, D1 or email service is required.** Deploy to your Cloudflare account and enter the same access token on each device. + +| Mode | Best for | Access | File storage | +| --- | --- | --- | --- | +| **Self-hosted (default)** | Your own image and text pool | Deploy, then enter your own `AUTH_TOKEN` | Your Cloudflare R2 | +| Hosted service (beta) | Using the operator's service without deploying | Register/sign in at the hosted URL | The operator's Cloudflare R2 | +| Read-only demo | Exploring the interface | Open the demo above; uploads are disabled | Public samples | + +For self-hosting, follow [the steps below](#deploy-your-own-5-min). See the [hosted guide](docs/hosted.md) for availability and quotas: the current beta still has a Free-plan CPU limitation and its authentication upgrade is not deployed. [Mode details and FAQ](docs/deployment-modes.md). + ![shotsync gallery](docs/screenshot.png) ## What it is @@ -44,7 +56,7 @@ The dividing line is **a live transfer vs. a pool that waits**. LocalSend and Pa **Choose shotsync if** you keep sending yourself screenshots and want them still there when you sit back down hours later, on a different machine, on a different network — and you would rather they lived in your own Cloudflare account than on a public image host. It replaces the habit of messaging things to yourself, not AirDrop. -**Do not choose shotsync if** you need per-user accounts: one shared token unlocks the whole pool. See the "Security model & limitations" section below before deploying. +**The default self-hosted mode has no per-user accounts:** one shared token unlocks the whole pool. Use the separate hosted mode if you need isolated accounts. See the "Security model & limitations" section below before deploying. ## Features @@ -56,11 +68,11 @@ The dividing line is **a live transfer vs. a pool that waits**. LocalSend and Pa - Single-token auth, constant-time compare, token never in URLs - 30-day auto-retention via R2 lifecycle - Runs entirely on the Cloudflare free tier (Workers + R2) -- ~50 tests (Vitest + `@cloudflare/vitest-pool-workers`) +- Tests (Vitest + `@cloudflare/vitest-pool-workers`) ## Deploy your own (~5 min) -Prereqs: a Cloudflare account, Node 18+, and **R2 enabled** (Dashboard → R2 → enable; Cloudflare asks for a card even on the free tier — the free allowance is not charged). +Prereqs: a Cloudflare account, Node.js 22+, and **R2 enabled** (Dashboard → R2 → enable; Cloudflare asks for a card even on the free tier — the free allowance is not charged). ```bash git clone https://github.com/Defiabell/shotsync @@ -73,7 +85,7 @@ npx wrangler r2 bucket create shotsync # 2. set the shared access token — any long random string; you enter it on each device openssl rand -hex 24 # generate one, copy it -npx wrangler secret put AUTH_TOKEN # paste it when prompted +npx wrangler secret put AUTH_TOKEN --config wrangler.toml --env "" # paste it when prompted # 3. deploy npm run deploy @@ -81,6 +93,10 @@ npm run deploy You also need a **workers.dev subdomain** (Dashboard → Workers & Pages, one-time) or a custom domain. After deploy you get `https://shotsync..workers.dev`. +`npm run deploy` explicitly uses `wrangler.toml` and deploys only the personal pool. It does not create an account database, request Supabase keys, or deploy the hosted service. `AUTH_TOKEN` is the ShotSync passphrase you generate, not a Cloudflare API token or Supabase key. Save it and share it only with people allowed to access the entire pool. + +After deployment, open the same URL and enter the same token on two devices. Upload a short text snippet and check it appears on the other device. An email registration screen means you opened the hosted service; use the personal URL returned by Wrangler instead. + ### 30-day retention Dashboard → R2 → bucket `shotsync` → Settings → Object lifecycle rules → delete objects 30 days after creation. @@ -125,7 +141,9 @@ Tap **`⚙`** in the top bar. The panel shows this pool's URL and the token this - **`显示`** (Show) toggles the full token; **`复制`** (Copy) puts it on the clipboard for pasting into another device. - **`退出登录`** (Log out) forgets the token on this device and returns to the token prompt. Nothing changes server-side; the same token still works elsewhere. -- **Single shared token.** Anyone with the URL **and** token can view/upload/delete. This is a single-user / trusted-circle tool, not multi-tenant — there are no per-user accounts and no way to "switch" tokens on one pool; a second pool is a second Worker deployment. Rotate with `npx wrangler secret put AUTH_TOKEN` — note this also invalidates all live share links, since the token is the link signing key. +## Security model & limitations + +- **Single shared token.** Anyone with the URL **and** token can view/upload/delete. This is a single-user / trusted-circle tool, not multi-tenant — there are no per-user accounts and no way to "switch" tokens on one pool; a second pool is a second Worker deployment. Rotate with `npx wrangler secret put AUTH_TOKEN --config wrangler.toml --env ""` — note this also invalidates all live share links, since the token is the link signing key. - **Share links are public** until they expire (7 days): anyone with the link can see that one item. - **Transit pool, not an archive.** Items auto-delete after 30 days by design. - **The UI is currently in Chinese.** i18n PRs welcome. diff --git a/README.zh-CN.md b/README.zh-CN.md index e2335d6..e46cfd7 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -6,6 +6,18 @@ **🎬 在线演示(只读示例池):https://shotsync-demo.defiabell.workers.dev** +## 选择使用方式 + +**自己部署是默认方式,不需要注册 ShotSync 账号,也不需要 Supabase、D1 或邮件服务。** 部署到自己的 Cloudflare 后,每台设备输入同一个访问令牌即可使用。 + +| 方式 | 适合谁 | 如何进入 | 数据存放 | +| --- | --- | --- | --- | +| **自己部署(默认)** | 想拥有自己的图片与文字池 | 部署后输入自己设置的 `AUTH_TOKEN` | 自己的 Cloudflare R2 | +| 公共托管服务(试用) | 不想部署,接受运营方存储数据和使用限额 | 在服务地址注册/登录 | 运营方的 Cloudflare R2 | +| 只读演示 | 先看看界面 | 打开上方演示地址;不能上传 | 公开样例 | + +自部署按[下面的步骤](#自己部署约-5-分钟)操作即可。公共服务的可用状态和限额见[托管版说明](docs/hosted.md);托管版目前仍有免费 CPU 限制,认证升级尚未上线。[模式区别与常见问题](docs/deployment-modes.md)。 + ![shotsync gallery](docs/screenshot.png) ## 这是什么 @@ -42,7 +54,7 @@ iCloud / AirDrop / 网盘 / 公开图床,要么手动、要么锁死在某个 **这些情况用 shotsync**:你老是要把截图发给自己,希望几小时后换台机器、换个网络坐下来时它还在;并且比起公共图床,你更愿意让这些东西待在自己的 Cloudflare 账号里。它替代的是「用微信发给自己」这个习惯,不是替代 AirDrop。 -**这些情况别用 shotsync**:你需要多用户各自的账号。整个池子只有一个共享 token,部署前请先看下面的「安全模型与限制」。 +**默认自部署模式不区分用户账号**:一个共享 token 解锁整个池子。需要用户隔离时使用独立的托管账号模式;部署前请先看下面的「安全模型与限制」。 ## 功能 @@ -54,11 +66,11 @@ iCloud / AirDrop / 网盘 / 公开图床,要么手动、要么锁死在某个 - 单 token 鉴权、constant-time 比较、token 永不进 URL - 30 天自动留存(R2 lifecycle) - 完全跑在 Cloudflare 免费档(Workers + R2) -- ~50 个测试(Vitest + `@cloudflare/vitest-pool-workers`) +- 自动化测试(Vitest + `@cloudflare/vitest-pool-workers`) ## 自己部署(约 5 分钟) -前置:一个 Cloudflare 账户、Node 18+、并**启用 R2**(控制台 → R2 → 启用;即使免费档 Cloudflare 也会要求绑卡——免费额度内不扣费)。 +前置:一个 Cloudflare 账户、Node.js 22+、并**启用 R2**(控制台 → R2 → 启用;即使免费档 Cloudflare 也会要求绑卡——免费额度内不扣费)。 ```bash git clone https://github.com/Defiabell/shotsync @@ -71,7 +83,7 @@ npx wrangler r2 bucket create shotsync # 2. 设置共享访问 token —— 任意长随机串;每台设备要输它 openssl rand -hex 24 # 生成一个,复制下来 -npx wrangler secret put AUTH_TOKEN # 提示时粘贴 +npx wrangler secret put AUTH_TOKEN --config wrangler.toml --env "" # 提示时粘贴 # 3. 部署 npm run deploy @@ -79,6 +91,10 @@ npm run deploy 你还需要一个 **workers.dev 子域名**(控制台 → Workers & Pages,一次性)或自定义域名。部署后会得到 `https://shotsync.<你的子域>.workers.dev`。 +`npm run deploy` 固定使用 `wrangler.toml`,只部署个人池;不会创建账号数据库、要求 Supabase 密钥或部署公共账号服务。`AUTH_TOKEN` 是你自己生成的 ShotSync 访问口令,不是 Cloudflare API Token,也不是 Supabase 密钥。请保存它,并只交给允许访问整个池子的人。 + +部署后,在两台设备输入相同的地址和令牌,上传一小段文字并确认另一台能看到,即可完成检查。若出现邮箱注册页,你打开的是托管服务地址,请改用 Wrangler 刚返回的个人实例地址。 + ### 30 天自动清理 控制台 → R2 → 桶 `shotsync` → Settings → Object lifecycle rules → 对象创建 30 天后删除。 @@ -117,7 +133,9 @@ npm run deploy - **`显示`** 切换明文;**`复制`** 放进剪贴板,拿去另一台设备粘贴。 - **`退出登录`** 只是让这台设备忘掉 token、回到输入页。服务端没有任何变化,同一个 token 在别的设备照常可用。 -- **单一共享 token。** 拿到「地址 + token」的任何人都能看/传/删。这是单人 / 可信小圈子工具,不是多租户——没有按用户区分的账号,同一个池子也没有「切换 token」这回事;想要第二个池子就再部署一个 Worker。用 `npx wrangler secret put AUTH_TOKEN` 轮换——注意这会同时让所有现存分享链接失效(token 也是链接的签名密钥)。 +## 安全模型与限制 + +- **单一共享 token。** 拿到「地址 + token」的任何人都能看/传/删。这是单人 / 可信小圈子工具,不是多租户——没有按用户区分的账号,同一个池子也没有「切换 token」这回事;想要第二个池子就再部署一个 Worker。用 `npx wrangler secret put AUTH_TOKEN --config wrangler.toml --env ""` 轮换——注意这会同时让所有现存分享链接失效(token 也是链接的签名密钥)。 - **分享链接是公开的**,直到过期(7 天):拿到链接的人都能看那一个 item。 - **中转池,不是归档。** item 按设计 30 天后自动删除。 - **界面目前是中文。** 欢迎提 i18n PR。 diff --git a/docs/deployment-modes.md b/docs/deployment-modes.md new file mode 100644 index 0000000..14b50b2 --- /dev/null +++ b/docs/deployment-modes.md @@ -0,0 +1,43 @@ +# ShotSync:选择部署与使用方式 / Deployment modes + +## 默认:部署自己的个人池 + +这是项目的主要使用方式。只需要自己的 Cloudflare 账号、一个 Worker、一个 R2 存储桶,以及自己生成的 `AUTH_TOKEN`。不需要注册 ShotSync 账号、Supabase、D1、邮件域名或验证码服务。 + +按 [中文快速部署](../README.zh-CN.md#自己部署约-5-分钟) 或 [English quick start](../README.md#deploy-your-own-5-min) 操作。`npm run deploy` 明确选择 `wrangler.toml`,入口是 `src/index.ts`;`npm run dev` 也使用同一配置。 + +部署成功后: + +1. 保存 Wrangler 返回的个人实例地址及自己生成的访问令牌。 +2. 每台设备打开该地址,输入相同令牌。令牌持有者共享整个池子,可查看、上传和删除。 +3. 在一台设备发送一小段文字,检查另一台能看到。 +4. 在 R2 配置 30 天删除规则。Worker 不会替你创建这条生命周期规则。 + +`AUTH_TOKEN` 是应用访问口令,**不要把 Cloudflare API Token、GitHub Token 或 Supabase Secret 填进网页**。令牌丢失时由部署者在自己的 Worker 上更换 `AUTH_TOKEN`;更换后各设备需重新输入,旧分享链接也会失效。 + +## 可选:直接使用公共托管服务 + +不想部署的用户可使用运营方提供的账号服务。浏览器通过邮箱和密码进入自己的文件池;文件存放在运营方的 Cloudflare 中,受服务人数、上传、存储和保留时间限制。使用者不需要开通 Cloudflare 或 Supabase。 + +托管服务与自部署实例的数据、登录账号和访问令牌不互通,不会自动迁移或同步。Mac App/快捷指令应填写所选服务的地址:个人池使用共享 `AUTH_TOKEN`,托管服务使用登录后创建的设备令牌。 + +当前公共服务仍为试用,原登录实现存在免费 CPU 限制,认证升级尚未部署;实际状态见[托管说明](hosted.md)。只读 demo 仅用于浏览公开样例,不接受上传,也不是公共账号服务。 + +## 仅运营者:部署多用户账号服务 + +[托管部署文档](hosted.md)面向想为多人运营服务的人。它有独立的 Worker 入口、D1 和 R2 资源;外部认证升级另需运营者的 Supabase 配置。不要把这套配置作为个人池的安装前提,也不要复制维护者的数据库 ID、存储桶或认证项目配置。 + +| 命令 | 配置 | 部署内容 | +| --- | --- | --- | +| `npm run deploy` | `wrangler.toml` | 无注册流程的个人 token 池(默认) | +| `npm run deploy:hosted` | `wrangler.hosted.jsonc` | 多用户账号服务,仅运营者使用 | + +升级个人池代码不会自动开启账号系统。两种模式维持独立入口和显式配置;不根据是否发现 Supabase 密钥自动切换。只读 demo 是第三个独立演示环境。 + +## English summary + +Self-hosting remains the default: Worker + R2 + one shared `AUTH_TOKEN`. Run `npm run deploy`; no ShotSync account, Supabase, D1, email or CAPTCHA setup is required. Token holders share the entire pool. Configure the 30-day R2 lifecycle explicitly. + +The optional hosted service uses individual accounts and the operator's storage/quotas. Only its operator needs the extra infrastructure; end users sign in at that service's URL. Accounts, files and credentials are not automatically shared with personal deployments. The hosted beta is still undergoing an authentication upgrade; see its guide for current availability. + +`npm run deploy:hosted` is an explicit, separate operator workflow. It never replaces the default personal deployment. The read-only demo is only for exploring sample content. diff --git a/docs/hosted.md b/docs/hosted.md index 2d169c2..69808b3 100644 --- a/docs/hosted.md +++ b/docs/hosted.md @@ -1,5 +1,7 @@ # Hosted ShotSync beta +> This guide is for operators running a multi-user service. To deploy a personal pool without accounts, use the [default README instructions](../README.md#deploy-your-own-5-min): Worker + R2 + `AUTH_TOKEN`, with no D1 or Supabase. See [mode selection](deployment-modes.md). + The hosted entry point (`src/hosted/index.ts`) adds email/password accounts with recovery codes and private per-account pools. It is a separate Worker, D1 database and R2 bucket. Existing personal deployments and the read-only demo retain their token-based behavior. The [hosted beta](https://shotsync-hosted.defiabell.workers.dev) is deployed on Workers Free; email delivery and a sender domain are not required. ## What people can do diff --git a/package.json b/package.json index 894d303..ce7a2c1 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "private": true, "type": "module", "scripts": { - "dev": "wrangler dev", - "deploy": "wrangler deploy", + "dev": "wrangler dev --config wrangler.toml --env \"\"", + "deploy": "wrangler deploy --config wrangler.toml --env \"\"", "test": "vitest run", "test:watch": "vitest", "typecheck": "tsc --noEmit", diff --git a/src/about.ts b/src/about.ts index aedcd32..942b335 100644 --- a/src/about.ts +++ b/src/about.ts @@ -58,7 +58,9 @@ export const aboutHTML = /* html */ `

shotsync:截图和文字,换台设备接着用。

shotsync 是一个运行在你自己的 Cloudflare 账号中的图片与文字暂存工具。在电脑上传截图,稍后从手机保存;在手机发一段文字,回到电脑复制。两台设备无需同时在线,也无需连接同一个 Wi-Fi。

-

演示站只有公开样例,不提供访客上传。想同步自己的内容,需要先部署独立实例。

+

演示站只有公开样例,不提供访客上传。自己部署是默认方式,无需注册账号或配置 Supabase;公共账号服务是另一个独立入口。

+ +

自己部署,还是直接使用服务?

自己部署:内容存放在你自己的 Cloudflare,输入一个访问令牌即可使用,无需邮箱、账号数据库或 Supabase。

公共托管服务:在运营方提供的地址注册登录,文件按账号隔离,适用运营方的限额和保留时间。公开试用仍在升级认证;查看可用状态与说明。两种方式的账号、访问令牌和文件不互通。

适合什么场景?

  • 工作时截一张图,过一会儿在另一台电脑或手机取走。
  • 把照片、链接或一段纯文字暂存在自己的池子,代替给自己发消息。
  • 给别人发送单个内容的临时分享链接,不开放整个图片池。
@@ -70,7 +72,7 @@ export const aboutHTML = /* html */ `

可选的 macOS 菜单栏客户端支持自动上传新截图,需要 macOS 13+ 和本地构建。iPhone 上可按 iOS 快捷指令教程从其他 App 分享图片到池子。

如何自部署 shotsync?

-

后端由一个 Cloudflare Worker 和一个 R2 存储桶组成。你需要自己的 Cloudflare 账号、启用 R2,以及能运行项目工具链的 Node.js 环境。

+

默认自部署后端只有一个 Cloudflare Worker 和一个 R2 存储桶,不需要 D1、Supabase 或邮件服务。你需要自己的 Cloudflare 账号、启用 R2,以及 Node.js 22+ 环境。

  1. GitHub 仓库克隆源码,安装依赖,使用 Wrangler 登录自己的 Cloudflare 账号。
  2. 创建 R2 存储桶,使其名称与项目的 wrangler.toml 配置一致。
  3. 生成足够长的随机 token,通过 Wrangler secret 设置 AUTH_TOKEN,然后部署 Worker。
  4. 在每台设备打开部署地址,输入同一个 token。
  5. 在 R2 的 Object lifecycle rules 中设置创建 30 天后删除对象。

30 天删除需要你配置 R2 生命周期规则,Worker 本身不会自动建立这条规则。重要文件请保留其他副本。完整命令及配置以 仓库部署说明为准。

代码采用 MIT 许可证。运行费用由你的 Cloudflare 用量和当前套餐决定,免费额度并不代表无限使用;部署前查看 WorkersR2 官方计费说明

@@ -86,6 +88,7 @@ export const aboutHTML = /* html */ `

常见问题

发送设备必须一直开着吗?

不用。上传完成后,另一台设备可以稍后通过互联网取回,直到内容被手动删除或被 R2 生命周期规则清理。

能直接用公开演示同步自己的截图吗?

不能。演示是只读样例池;自己的数据应放在自己部署的实例中。

+

自部署需要注册账号或申请 Supabase 密钥吗?

不需要。默认部署使用你设置的访问 token;它不是 Cloudflare API Token。账号体系只用于独立的多用户托管服务。

token 泄露了怎么办?

在自己的 Worker 上更新 AUTH_TOKEN,并在各设备重新输入。更新 token 也会使此前签发的分享链接失效。

为什么上传后另一台设备看不到?

先确认两台设备打开的是同一个部署地址,token 一致,上传已成功。等待一次自动刷新;如果仍失败,检查浏览器请求及 Worker 日志。仅打开网页不能完成设备间同步,内容必须先上传成功。

diff --git a/src/gallery/page.ts b/src/gallery/page.ts index 29d15bc..86cbe45 100644 --- a/src/gallery/page.ts +++ b/src/gallery/page.ts @@ -57,7 +57,8 @@ export const galleryHTML = /* html */ `