服务商与自建
如何选择官方实例、自建参考服务器或任何符合标准的 URL,服务商需要实现哪些接口,以及如何运行和配置参考服务器。
提供云服务的服务器叫作服务商。PKU harness 不绑定某一家服务商:只要服务器实现了云服务协议,App 就能使用它。本页前半部分面向用户,说明如何选择服务商;后半部分面向运营者,说明服务商要实现什么,以及如何运行开源的参考服务器。
选择服务商(用户)
在「设置 → 云服务」里有三个选项。
官方是由 pkuinfo 运营的实例,目前还没有部署。它上线后会保持精简,只提供实时分享用的中继、小容量的端到端加密存储和查看页。在你主动开启之前,它默认处于关闭状态。
自建需要你填写一个基础 URL。点测试连接后,App 会显示这个服务商在 /v1/meta 里返回的运营者、服务和限额。
关闭表示不使用云服务。必须依赖云服务的插件会变为不可用;云服务对其可选的插件照常在本地工作。
URL 必须使用 HTTPS。开发版额外允许 http://10.0.2.2:*、http://localhost:* 和 http://127.0.0.1:*。切换服务商不会迁移数据,因为每家服务商上的设备身份和存储都是独立的。
服务商需要实现什么
服务商需要实现 API 参考里的全部接口,并用 @pku-harness/cloud-protocol 的 schema 校验数据。具体包括:
GET /v1/meta。它返回protocol: 1、提供的服务、限额、工作量证明参数、查看页、函数,以及运营者信息(name、contact,可选privacyURL)。- 设备注册和 token 签发。注册时设备要先完成工作量证明。设备用签名换取 token 时,
aud必须是你自己的源,允许 5 分钟的时钟偏差,并防止 nonce 重放。token 的有效期为 10 分钟。 - 你在
services里列出的服务。服务商可以只提供其中一部分,uses没有被完全覆盖的插件会被标为不可用。 - 统一的错误响应体
{ error: { code, message, retryAfterS? } },以及Retry-After和RateLimit-*响应头。 /w/<plugin>/<page>下的静态查看页,并带有严格的内容安全策略(Content Security Policy,CSP);以及GET /s/:id重定向。
参考服务器
开源的参考服务器位于 pku-harness-plugins 仓库的 packages/cloud-server 目录。它基于 Bun、Hono 和 bun:sqlite(WAL 模式),并用 @pku-harness/cloud-protocol 的 schema 校验每个请求和响应。
参考服务器声明提供 store、channels 和 functions 三项服务,push 目前返回 501 unsupported。插件服务端函数(/v1/fn、/v1/p)受 CLOUD_FN_POLICY 控制。在生产环境(NODE_ENV=production)中,它的默认值是名单为空的 allowlist。官方服务器不开启服务端函数。
在本地运行参考服务器:
cd pku-harness-plugins/packages/cloud-server
bun run dev # http://localhost:8787,改动后自动重载,数据保存在 ./data/cloud.db
bun test # 路由测试,以及真实的 WebSocket/SSE 测试
# 也可以在仓库根目录运行:bun run --filter @pku-harness/cloud-server dev在 Android 模拟器里,把「设置 → 云服务 → 自建」指向 http://10.0.2.2:8787。
参考服务器通过环境变量配置:
| 变量 | 默认值 | 含义 |
|---|---|---|
PORT / HOST | 8787 / 0.0.0.0 | 监听地址 |
CLOUD_PUBLIC_URL | http://localhost:$PORT | 客户端访问用的源,也是 token 挑战里的 aud |
CLOUD_DB | ./data/cloud.db | SQLite 文件(临时运行可以用 :memory:) |
CLOUD_TOKEN_SECRET | 自动生成并存进数据库 | bearer token 的 HMAC 密钥(至少 32 个字符) |
CLOUD_POW_DIFFICULTY | 16 | 工作量证明难度 |
CLOUD_POW_ROTATE_S | 21600 | salt 轮换周期;上一个 salt 会再多有效一个周期 |
CLOUD_OPERATOR_NAME / CLOUD_OPERATOR_CONTACT / CLOUD_PRIVACY_URL | PKU harness Cloud (self-hosted) / 空 | 由 GET /v1/meta 返回 |
CLOUD_PAGES_DIR | <plugins repo>/plugins | 存放 <plugin>/web/dist 查看页的目录 |
CLOUD_TRUST_PROXY | 关闭 | 设为 1 时,客户端 IP 取 X-Forwarded-For 的最后一跳(部署在 Caddy 后面时使用) |
deploy/ 目录里有 Dockerfile、Caddyfile 和 Litestream 配置,用法见其中的 README.md。服务端函数相关的变量(CLOUD_FN_POLICY、CLOUD_FN_ALLOW、CLOUD_FN_VERIFIED、CLOUD_FN_LOCAL、CLOUD_SECRET_<PLUGIN>__<NAME>)写在服务器自己的 README.md 里。
运营一个实例
如果你打算为别人运营一个实例,请注意以下几点:
- 公开你的身份(
operator.name、contact),并发布隐私声明(privacyURL)。 - 不要在日志里记录数据内容和 token。数据虽然是密文,但 IP 地址和请求时间同样属于个人信息。
- 在中国大陆托管服务需要 ICP 备案。官方实例计划部署在大陆以外,并为分享链接准备一个专用的短域名。微信可能会对陌生域名显示拦截提示,所以 App 总是同时提供二维码和复制链接两种方式。