一人公司:用无服务器架构打造私有包仓库
善战者之胜也,无奇胜,无智名,无勇功。 —— 孙子
题记:这是「一人技术公司」系列的第四篇。现在 OPC (One Person Company) 的概念很火,我也尝个鲜,看看真要严肃地使用周末来做点一家技术公司才能做起来得事情,到底能做成啥样。这并不意味着我要全职创业,我认为我自己是个一直在路上的创业者,朝九晚五从来不是我的束缚。我想通过这个过程,了解 AI 的边界,以及我自己的边界。
整个系列将记录我从零搭建一套完整技术体系的全过程 —— 从基础设施,到网络与运行时,到核心框架,再到应用服务。这不是一篇教程,而是一份带有思考过程的实战手记。
前三篇我们分别讲了安全框架、k8s 多层架构和无服务器应用框架。今天聊一个很多独立开发者容易忽略、但代码库一大就躲不掉的问题:私有包仓库。
如果你一个人撑着一家技术公司,或者三五个人的小团队同时养着好几个项目,迟早会碰到这种场景:写了个通用工具库,想在三四个项目里复用;封装了一些内部业务逻辑,不方便开源但需要跨项目共享;CI/CD 流水线需要拉取私有依赖。这时候,你需要的就是一个私有包仓库。
听起来挺简单,对吧?装一个现成方案不就完事了?
没那么简单。不过有一个好消息:在 AI 时代,「从零搓一个私有仓库」这件事,从「劝退 90% 的开发者」变成了「半天就能搞定」。
为什么需要私有仓库?
你可能会说:代码丢私有 Git 仓库里,用 Git 依赖引用不就得了?
这招初期确实能凑合。Cargo 支持 git = "https://..." 的依赖声明,NPM 也支持 Git URL。但代码库一大,痛点就来了:
第一,版本管理约等于没有。 Git 依赖本质上锁定到某个 commit 或 branch,没有语义化版本(semver)的约束。十几个内部库互相依赖的时候,没有版本号管着,分分钟变成灾难现场。你改了 A 库的接口,B、C、D 库集体炸裂,你根本不知道哪个版本还能用。
第二,构建速度肉眼可见地劣化。 每次构建都要从 Git 仓库拉完整代码,编译耗时随依赖数量线性增长。正经的包仓库提供预编译制品(artifact),构建速度能快一个数量级。
第三,生态工具链直接断链。 Cargo 和 NPM 的工具链(版本解析、依赖树分析、安全审计)都是围绕包仓库协议设计的。你用 Git 依赖等于绕过了整个生态,大量好用的工具直接废掉。
所以,当内部代码库超过五六个互相依赖的库,私有仓库就从「锦上添花」变成了「生存刚需」。
现有方案的成本困境
OK,需求明确了。市面上有啥现成方案?
设身处地想一下,你是一人公司或三五人的小团队,面前摆着这些选项:
托管 SaaS 方案: Cloudsmith、Artifactory Cloud 这类服务。功能是全的,但价格也是真不便宜。一个月就几百次 publish、几千次 download 的小团队,每月几十到上百美元的费用,属实没必要。而且很多方案不同时支持 Cargo 和 NPM,搞不好得买两份。
自托管开源方案: Verdaccio(NPM)或 Kellnr(Cargo)。看着是免费的,但你得养一台常驻服务器。最便宜的 EC2 也要每月十几刀,加上存储、带宽、运维这些隐性成本,实际开销也不低。更要命的是,你得维护它。服务器一挂,所有项目的 CI/CD 全线瘫痪。一个人的团队,运维一台有状态服务器的心智负担真的扛不住。
GitHub Packages / GitLab Packages: 还算不错,但有局限。GitHub Packages 对 Cargo 的支持长期摆烂在实验状态,NPM 支持尚可但被锁死在 GitHub 生态里。你的基础设施不在 GitHub 上的话,集成成本很高。
这就引出了一个灵魂拷问:有没有可能搞一个几乎零运维、月成本 10 美元以内、还同时支持多个包管理器的私有仓库?
答案是:能。用无服务器架构,而且我们刚刚完成了 operon 框架。
回到第一性原理:包仓库到底需要什么?
在动手之前,先把包仓库的外壳扒开,看看里面到底需要啥。
回到第一性原理,一个包仓库需要且仅需要这几项能力:
- 认证与授权:搞清楚「你是谁」「你能干啥」
- 包的存储与检索:上传制品、下载制品
- 元数据索引:让包管理器知道有哪些包、哪些版本、依赖关系怎样
- 版本管理:支持 semver 约束、yanking(撤回)等操作
就这四样。没有复杂的实时通信、没有长连接状态、没有计算密集型任务。每一个操作都是短暂的、无状态的 HTTP 请求-响应。
这不就是无服务器架构的舒适区吗?
而且你仔细看这四项需求,每一项的难度都不在「创造性」上,而在「协议细节的精确实现」上。Cargo 稀疏索引协议的每个字段怎么拼、NPM 包文档的 JSON 结构长什么样、HTTP 头该怎么设……这些东西读 RFC 和源码就能搞清楚,但纯靠人肉去啃,枯燥且容易出错。这恰恰是 AI 最擅长的活儿。 你把 RFC 文档和协议规范喂给 Claude Code,它能又快又准地把规范翻译成可运行的代码。你只需要把控架构决策和边界条件,脏活累活交给 AI 去干。
这个认知很重要:AI 没有改变「你需要什么」,但它彻底改变了「你能做什么」。 以前自建私有仓库的 ROI 算不过来,光是啃完两个包管理器的协议规范就够你喝一壶的。现在有了 AI,从规范到实现的距离被大幅压缩,自建方案的可行性一下子就起来了。
把这四个需求映射到 AWS 托管服务上:
- S3 存包的二进制制品和索引文件,容量无上限,按用量计费
- DynamoDB 存包的元数据、用户信息和审计日志,按需计费,零流量零费用
- Lambda 处理所有 API 请求,按调用次数计费,不用不花钱
- CloudFront 做 CDN 和请求入口,边缘缓存拉满,减少 Lambda 调用
- JWT 做认证,纯签名校验,不碰数据库
每个组件都是「用多少付多少」的模式。对于小团队的用量,月成本可以压到个位数。
整体架构设计
把完整架构摊开来看。这个系统的核心设计原则:
- 零运维无服务器:没有一台需要你操心的服务器,全部用 AWS 托管服务
- 单一 Lambda 函数:一个 Rust 二进制文件搞定所有路由(Cargo + NPM + 认证)
- 无状态认证:JWT 令牌通过 Ed25519 签名自校验,不碰数据库
- 边缘加速:Lambda@Edge 在 CloudFront 边缘节点验证 JWT,非法请求永远到不了源站
- 协议可扩展:认证/存储/审计层共享,不同包管理器的协议处理随插随拔
整体请求流程长这样:
这里面有几个关键的架构决策,值得展开聊聊。
为什么选 JWT 而不是传统 Token?
这是个牵一发动全身的决策。传统私有仓库(比如 Artifactory)用的是不透明 token:客户端发 token,服务端去数据库里查对应的用户和权限。这种模式的问题在于,每一次请求都要查一次数据库。
在无服务器架构下,这意味着每次 cargo build(可能触发几十次索引查询和下载请求)都会产生几十次 DynamoDB 读取。延迟有了,费用也有了,双重暴击。