作品

Sub2API

自托管的个人 OpenAI 兼容网关:把手上的模型订阅统一包装成一个接口,供所有个人工具复用。

为什么做

个人工具一多,一个重复劳动就浮出来:每写一个要用 AI 的工具,就要接一遍模型——配 API 地址、管一份密钥、处理一种计费。Raycast 扩展接一遍,速记应用接一遍,实验项目再接一遍。而我手上真正的模型能力来源是几份订阅,订阅的接口形态和标准 API 并不一致,没法直接给工具用。

Sub2API 解决的就是这一层:把订阅包装成标准的 OpenAI 兼容接口。工具侧只需要知道一个 base URL 和一个 key,背后用什么订阅、怎么认证,都收在网关里。

它是什么

Sub2API 是跑在我自己机器上的一个 Docker 服务,对外通过 Cloudflare Tunnel 暴露为一个 HTTPS 域名下的 /v1 接口。任何支持自定义 OpenAI 接口地址的工具——我的随心记、Raycast 扩展、各种实验脚本——填上这个地址就能用。

它是「个人 AI 基建」这个思路的基础层:把各种订阅统一成 OpenAI 兼容接口,一处接入、处处复用。模型能力对个人开发者来说是易变的——订阅会换、模型会升级、新服务会出现——把易变的部分隔离在网关后面,工具侧的代码就可以保持稳定。

技术要点与设计决策

自托管加隧道的部署形态是刻意的选择。服务跑在本机 Docker 里,不租云服务器;对外访问经 Cloudflare Tunnel 打通,不在家庭网络上开任何入站端口。个人服务的流量规模用不上独立服务器,而隧道方案把「有公网可达的 HTTPS 服务」的成本压到接近零:一个常驻进程,证书和域名解析全部由 Cloudflare 处理。

对外地址统一为 HTTPS 域名。工具配置里一律写域名,不写本机端口——这样服务迁移、端口调整都不需要动任何工具的配置,域名是唯一的稳定契约。

运维上积累了一份故障模式对照:Cloudflare 返回 530 表示隧道断了,请求根本没到应用层,去查隧道进程;/v1/models 正常返回但生成请求 503,表示上游订阅的认证过期,去重新登录上游账号。自托管服务没有值班团队,「出问题时按现象直接定位到层」的经验清单就是它的运维手册——每种故障见过一次,下一次三分钟内恢复。

边界也很清楚:这是单用户网关,不做多租户、不做用量统计面板、不做负载均衡。它要伺候的用户只有一个人,按这个规模设计,复杂度才压得住。

当前状态

自用运行中。它和我的其他自托管服务(Agent 协作平台、个人 Skill 分发机制等)构成同一套个人基建:跑在自己机器上、用隧道对外、为自己的工具服务。这一层平时不产出任何可见的东西,但上面每个工具都因为它少写了一遍模型接入。