P3 — 阶段 13–14:VPS Docker 自托管
未来条目与阶段规划维护在规划总览。当前正式部署为 Cloudflare Workers + D1,通过 Telegram Webhook 接收更新。VPS Node / SQLite / Docker 尚未实现、未排期。
本页规划同一代码库支持 Cloudflare Workers 与 VPS Docker 两种部署平台,保留 Cloudflare 路径。以下选型比较说明规划目的与边界,不是可执行的 VPS 部署教程,也不表示两平台已功能一致。
可行性评估方向(2026-09-30,启动时重新核验)
现状是 Cloudflare Workers(workerd 运行时)+ D1,不是 Node 服务,直接加 Dockerfile 不可行。评估时的有利条件包括零运行时依赖、Web 标准 API 与纯函数路由;启动时须按最新源码核验运行时依赖与 D1 接口实际用量。
既定路线:可移植核心改造 + Node 24 第二入口(内置 node:sqlite,零新增运行时依赖),而非容器包装 wrangler dev 的开发模拟器方案。
VPS 规划优先采用长轮询(getUpdates),也规划 Webhook;后者需公网 HTTPS(反代 / 隧道)。免域名、免入站 TLS 仅限长轮询接收 Telegram 更新,其他 HTTP 能力另行判断。
部署选型:为什么规划 VPS
增加 VPS 的目的不是替代 Cloudflare,而是让已有服务器的用户复用主机,并自主控制 Node 运行环境与 SQLite 文件。平台选择与更新接入方式是两个维度:Cloudflare 当前使用 Webhook,VPS 规划首选长轮询,也规划 Webhook。
Cloudflare 与 VPS 的取舍
| 维度 | Cloudflare Workers + D1(已交付) | VPS Docker + SQLite(规划) |
|---|---|---|
| 基础设施 | 托管运行时、数据库与 HTTPS,减少主机维护 | 可复用已有服务器,但须自行维护系统安全、进程重启与监控 |
| 环境与数据控制 | 遵循 Workers / D1 运行模型,通过平台管理配置与数据 | 自主控制运行环境与 SQLite 文件;持久卷不等于备份,须负责一致性备份与恢复验证 |
| 更新接入 | 当前由 Telegram 向公网 HTTPS Webhook 推送 | 首选出站长轮询;Webhook 需另行配置公网 HTTPS |
| 资源与故障责任 | 受平台套餐、配额与服务可用性约束 | 自行规划 CPU、内存、磁盘和网络;单主机故障会中断服务 |
| 成本 | 取决于 Cloudflare 套餐与配额 | 包含主机、备份、带宽与维护成本;复用已有主机不等于零成本 |
| 外部依赖 | 依赖 Telegram;启用 Turnstile 时还依赖该验证服务 | 仍依赖 Telegram;若后续支持并启用 Turnstile,仍依赖 Cloudflare 的该服务 |
VPS 不意味着媒体迁到本地,也不承诺更便宜、更快或更稳定。延迟与可靠性取决于网络、实现质量和运维,不能仅凭 Webhook / 长轮询或部署平台判断。
长轮询的机制与边界
- 不是忙轮询:VPS 主动向 Telegram 发出
getUpdates请求,Telegram 可等待新消息到达后响应,或超时后结束;客户端再发下一次请求,并非短间隔反复查询。 - 降低入站门槛:Telegram 不必访问 VPS 的入站端点,更新接入无需域名或入站 TLS。VPS 仍须稳定出站访问 Telegram API(HTTPS),主机、进程与网络维护不能省略。
- 消费与恢复责任:规划仅支持单实例消费同一 Bot 的更新,不做集群。未来实现须正确保存消费进度、复用幂等状态机,并处理超时、重试与退避;长轮询本身不保证消息处理可靠。
- 同 Token 切换:同一 Bot 的 Webhook 与
getUpdates互斥。规划启动轮询时先deleteWebhook;切换前须停用旧部署,禁止 Cloudflare 与 VPS 同时争抢同一 Token 或旧部署重新绑定 Webhook。
长轮询不提供验证页面
若后续 VPS 实现支持 Turnstile,仍须提供用户可访问的 HTTPS 验证页面、授权主机与密钥。轮询没有入站 Webhook 请求可供推导页面地址,必须另行明确公开 HTTPS origin 的配置。
VPS 的 Turnstile 支持范围、具体接线、配置及诊断方式以未来实现验收为准。不能把「轮询接入免域名 / 入站 TLS」理解为所有功能都无需公开 HTTPS 页面。
场景建议
- 希望现在部署、减少基础设施维护:选已交付的 Cloudflare 路径,并确认 Workers / D1 套餐与配额适合使用量。现有三条部署路径都是 Cloudflare 的操作途径,不是三个平台。
- 已有服务器、需要环境与数据文件控制:可关注 VPS 规划,前提是愿意承担资源、安全、监控与备份恢复责任;待实现并验收后再按届时指南部署。
- 没有公网入站入口、但可稳定访问 Telegram:未来可考虑 VPS 长轮询以降低更新接入门槛;若需要 Webhook 或 HTTPS 验证页面,仍须满足相应公开访问条件。
阶段 13 — 双运行时可移植核心
交付:共享层(routes / pipeline / store / telegram)与 Workers 运行时解耦,类型收窄为可移植形态;行为零变化,Cloudflare 部署路径不受影响。
不做:不实现任何 Node 运行时代码、不新增依赖、不改 Cloudflare 部署与数据库。
依赖:阶段 2–3 已验收;推荐阶段 7 稳定基线后启动。
- T59 可移植类型 HodorEnv / HodorDB —— 验证:共享层不再直接引用
Cloudflare.Env/ 全局D1Database(按实际用量结构兼容收窄),typecheck 与全部现有测试绿,Workers 行为不变。 - T60 共享路由 route() 抽取 —— 验证:Workers 入口与未来 Node 入口共用同一分发逻辑;/health、管理端点、/webhook 回归行为不变。
验收:typecheck 与现有 vitest 全绿,npm run deploy 部署后功能回归无差异;共享层对 Workers 运行时零硬编码依赖。
阶段 14 — VPS Docker 自托管
交付:规划 Node 24 + node:sqlite 第二运行时与容器交付,含长轮询模式;仅 Telegram 更新接入可在裸 VPS 上免域名、免入站 TLS。
不做:不替代 Cloudflare 部署路径;不做多实例 / 集群与分布式幂等;webhook 模式不自带 TLS(交给反代 / 隧道)。
依赖:阶段 13。
- T61 node:sqlite D1 形状适配器 + 迁移 runner —— 验证:prepare/bind/first/run 与 RETURNING 语义对齐 D1,PRAGMA user_version 跟踪迁移,重复启动不重复执行,单测覆盖往返与建表。
- T62 Node HTTP 入口与 process.env 装配 —— 验证:HODOR_DB_PATH / RUN_MODE(webhook|polling)/ PORT 运行时变量生效,必填缺失 fail-fast 且可诊断,/health 返回 200。
- T63 getUpdates 长轮询模式 —— 验证:单实例消费,与 webhook 互斥,启动先 deleteWebhook,切换前停用同 Token 的旧部署;复用 processed_updates 幂等状态机;仅更新接入免域名、免入站 TLS,出站 Telegram 可达;双向收发、重推 / 幂等 / 毒丸行为与 webhook 一致,日志不泄漏 token。
- T64 Docker 交付 —— 验证:多阶段 Dockerfile(node:24-slim)、非 root 运行、VOLUME /data 持久化、HEALTHCHECK /health,compose + env 示例开箱可用;容器重建数据不丢。
- T65 用户选型与部署文档 —— VPS 实现交付时同步完成并验证:
docs/guide/deploy.md成为统一部署入口:先比较平台、说明适用场景与长轮询边界,再链接对应教程;保留现有 Cloudflare 路径,不重复 Docker 操作步骤。- 新增
docs/guide/deploy-docker.md:按实际实现给出 Docker 配置、持久化、备份恢复及模式切换说明;从零 VPS 跑通轮询与 webhook,明确 HTTPS 前提及单实例限制。 - README 提供 Cloudflare / VPS 两个部署入口;同步
docs/guide/architecture.md与受影响的配置、功能、运维说明,明确平台差异和 Turnstile 实际支持边界,不承诺未经验证的功能对等。 - 检查选型入口、教程、README 与架构等页面互链及描述一致,
npm run docs:build通过;用户能先选平台,再按对应教程完成部署与验收。
阶段验收(未来交付时):
- docker compose up 后,单实例轮询在出站 Telegram 可达的裸 VPS 完成双向聊天冒烟;免域名、免入站 TLS 仅指更新接入,不涵盖验证页面。
- SQLite 数据落挂载卷,容器重建不丢;按文档验证备份恢复;Cloudflare 路径部署与功能不受影响。
- T65 的统一选型入口、Docker 指南、README 双入口、架构及受影响的配置 / 功能 / 运维文档同批更新,互链检查与文档构建通过;从零 VPS 实测两种模式及同 Token 的互斥切换。