
AI开发配置系统(二):我与AI的72小时:从零打造ConfigBridge

📖 本文是「AI开发配置系统」系列第二篇。上一篇:AI开发配置系统(一):告别手动Lucky配置:我为什么要自己造一个ConfigBridge
TL;DR(太长不看版)
- 背景:在上一篇文章中,我介绍了 ConfigBridge 的功能和使用场景
- 本文焦点:从 0 到 1 的真实开发过程,以及 AI 结对编程的体验
- 时间线:72 小时完成 MVP → 一个月打磨成完整产品
- 技术栈:FastAPI + Vue 3 + SQLAlchemy + Jinja2 模板引擎
- 核心收获:AI 不是替代,而是杠杆——让个人开发者也能突破技术边界
开篇:关于"72 小时"的真相
先说实话:标题里的"72 小时"有点标题党了。
严格来说,72 小时只够我完成一个勉强能跑的 MVP(Minimum Viable Product,最小可行产品)。这个 MVP 能做什么呢?
- ✅ 创建服务、服务器、模板的基本增删改查(CRUD)
- ✅ 变量系统的雏形(但只有两层优先级)
- ✅ 最基础的配置生成(但没有批量,没有远程部署)
- ✅ 一个"能用但丑陋"的前端界面
但这离"完整产品"还差得远。
从 MVP 到你在上一篇文章里看到的那个功能完善、界面美观的 ConfigBridge,我又花了将近一个月的时间:
- 🔧 变量系统从两层扩展到四层
- 🔧 加入远程部署、自动备份功能
- 🔧 加入配置版本控制
- 🔧 前端界面推翻重做了两次
- 🔧 无数的 Bug 修复和边界情况处理
所以更准确的说法是:72 小时从 0 到 MVP,一个月从 MVP 到产品。
但这恰恰是 AI 结对编程的价值所在——如果没有 AI,72 小时我可能连 MVP 都搞不定。
第一章:凌晨一点的决定
故事要从那个失眠的夜晚说起。
凌晨一点,我盯着散落在三台服务器上的几十个配置文件,做了一个决定:
自己造一个配置管理工具。
问题的背景我在上一篇文章中已经详细描述过了:IPv6 服务器、FRP(一种内网穿透工具)、多机 Nginx 配置……每新增一个服务,就要手写 4 份配置文件,分布在 2 台机器上。10 个服务意味着 40+ 份配置,任何一个拼写错误都可能导致服务不可用。
这不是技术问题,是效率问题。而效率问题,正是工具应该解决的。
我躺在床上,脑子里开始构思这个工具的雏形:
- 需要一个中心化的管理界面,所有服务、服务器、配置都在一个地方
- 需要模板系统,写一次模板,复用 N 次
- 需要变量系统,同一套模板在不同环境下生成不同配置
- 需要一键生成,点一下按钮,所有配置文件自动生成
想着想着,突然来了精神——我爬起来,打开电脑,开始和 AI 聊这个项目。
第二章:与 AI 结对——72 小时冲刺 MVP
我打开 Cursor,开始和 AI 讨论这个需求。
2.1 需求梳理:5 分钟定义核心概念
我告诉 AI:
"我需要一个配置管理系统。用户输入服务名、子域名、端口,系统自动生成 Nginx 配置、FRP 配置等。不同服务器需要不同的配置模板。"
AI 很快帮我梳理出几个核心概念:
| 概念 | 说明 | 示例 |
|---|---|---|
| 服务 (Service) | Web 服务的抽象 | 名称、子域名、端口 |
| 服务器 (Server) | 物理/虚拟服务器 | IP、SSH 凭证、是否 IPv6 |
| 配置模板 (Template) | Jinja2 格式模板 | Nginx 模板、FRP 模板 |
| 变量 (Variable) | 可自定义的配置项 | 监听端口、后端地址 |
2.2 核心设计:变量覆盖系统
这是我和 AI 花了最多时间讨论的部分。
问题:同一个模板,在不同服务器上生成的配置可能有细微差别。比如服务器 A 需要监听 IPv6,服务器 B 的端口要改成 FRP 转发端口……如果为每个场景单独写模板,模板数量会爆炸。
我向 AI 描述了这个问题,它几乎立刻给出了解决方案:
AI:"你需要一个变量覆盖系统。从全局到服务级别,层层覆盖。就像 CSS 的优先级规则一样。"
这个类比让我茅塞顿开!
这就好比公司的规章制度:
- 公司级规定(全局变量):全公司早上 9 点上班。
- 部门级规定(服务变量):开发部比较特殊,早上 10 点上班。
- 部门级自动覆盖了公司级。
72 小时内,我们快速实现了一个简单的两层变量系统:
服务变量(高优先级)
↓
全局变量(低优先级)当时的设计逻辑很简单:全局变量定义默认值,服务变量覆盖特定服务的配置。这对于 MVP 来说已经够用了。
但我心里隐隐觉得这还不够——如果同一个服务在不同服务器上需要不同的配置呢?这个问题我先记下了,留待后续解决。
2.3 模板语法:Jinja2 的魔力
ConfigBridge 的模板使用 Jinja2 语法。这是一个可行的 Nginx 模板:
server {
listen {{vars.listen_port}} ssl;
server_name {{service.name}}.{{global.base_domain}};
ssl_certificate {{vars.ssl_pem_path}};
ssl_certificate_key {{vars.ssl_key_path}};
error_page 497 =301 https://$host:{{vars.listen_port}}$request_uri;
{% if vars.is_nginx_webdav_config is defined and vars.is_nginx_webdav_config %}
include conf.d/webdav_params;
{% endif %}
location / {
proxy_pass http://127.0.0.1:{{service.port}};
include proxy_params;
}
}变量来源解读:
{{ service.xxx }}:来自服务数据(名称、端口等){{ server.xxx }}:来自服务器数据(IP、是否 IPv6 等){{ vars.xxx }}:来自变量系统(自动合并后的结果){{ global.xxx }}:来自全局配置
2.4 技术栈:为什么选择它们
| 层级 | 技术选型 | 选择理由 |
|---|---|---|
| 后端框架 | FastAPI | 异步、自带 OpenAPI 文档、类型提示友好 |
| ORM | SQLAlchemy 2.0 | 成熟稳定、支持异步 |
| 模板引擎 | Jinja2 | 功能强大、语法优雅、与 Python 生态无缝集成 |
| 前端框架 | Vue 3 | 响应式、组合式 API 开发体验佳 |
| UI 组件库 | Element Plus | 组件丰富、文档完善 |
| 部署 | Docker | 容器化、环境一致性 |
第三章:72 小时后的 MVP
经过 72 小时的密集开发,ConfigBridge 的第一个可运行版本诞生了。
说是"可运行",其实还很粗糙:
MVP 能做什么
- ✅ 服务管理:创建、编辑、删除服务,关联到服务器
- ✅ 服务器管理:记录服务器信息(名称、IP)
- ✅ 模板管理:创建 Jinja2 模板
- ✅ 变量系统(两层):全局变量 + 服务变量
- ✅ 配置生成:选择服务和服务器,生成配置文件
MVP 不能做什么
- ❌ 没有"服务-服务器变量"(四层变量的关键一层)
- ❌ 没有远程部署,只能手动 SCP
- ❌ 没有配置版本控制
- ❌ 没有批量操作
- ❌ 前端界面……一言难尽
第一次用自己的工具
尽管如此,我还是用这个 MVP 给自己的一个新服务生成了配置。
那种感觉就像——你造了一辆自行车,它歪歪扭扭的,刹车有点不灵,但它真的能骑!
从输入服务信息到生成 2 台服务器的 4 份配置文件,只用了不到 1 分钟。而以前,这个过程需要 30 分钟的复制粘贴和反复检查。
从 30 分钟到 1 分钟——这就是 MVP 的价值。
它证明了这个方向是对的。接下来要做的,是把它打磨成一个真正好用的产品。
第四章:从 MVP 到产品——一个月的打磨
72 小时的冲刺之后,是一个月的持续迭代。
4.1 阵痛与推倒重来:那次惨痛的“删库”
MVP 虽然跑通了,但随着我开始往里面塞更多的功能,代码开始失控了。
由于最初 72 小时冲刺时为了快,很多逻辑都写得极其随意,变量命名混乱,数据库关联也设计得一塌糊涂。当我试图修复一个“变量覆盖”的 Bug 时,往往会触发另外三个关于“模板渲染”的 Bug。
那是一个周三的深夜,我看着满屏的 TODO 和打了无数补丁的 service.py,意识到这已经不是在修补代码,而是在往屎山上盖别墅。
我做了一个决定:删除代码,推倒重来。
我没有在原有的代码上继续修补,而是直接新建了一个 v2 分支,执行了原代码删除。我把过去 72 小时积累的经验(以及踩过的坑)重新梳理,用更严谨的 OOP(面向对象编程)设计模式和更清晰的数据库结构(Schema)重新构建了核心引擎。
这里我有一个很深的感触:在 AI 时代,“推倒重来”不再是一个沉重的决定。
AI 写代码的速度极快,这使得重构甚至重写的“物理成本”被大大压缩了,剩下的仅仅是“心理负担”。既然代码实现变得如此廉价,我们完全可以将“推倒重来”作为一个并不昂贵的可选项。
前期多花点心思做好设计,远比在错误的架构上缝缝补补要划算得多。
虽然这让进度看起来倒退了三天,但正是这次“归零”,才有了后来能够稳定承载复杂配置的架构。
4.2 变量系统升级:从两层到四层
还记得 72 小时冲刺时留下的那个问题吗?——"如果同一个服务在不同服务器上需要不同的配置怎么办?"
在实际使用中,这个问题很快暴露出来了。
问题:同一个服务(比如 Nextcloud),在服务器 A 上的 backend_port 是 8080(直连),在服务器 B 上却是 8081(FRP 转发端口)。两层变量系统没法表达这种"服务 + 服务器"的组合关系。
我又跟 AI 进行了一轮深入讨论:
AI 的扩展方案:
我为您设计了一个扩展方案:
- 服务级变量:当
server_id为 NULL 时,视为该服务的全局默认值- 服务器级变量:当
server_id指定了具体 ID 时,覆盖服务级变量- 全局变量:新增一个专门的
GlobalVariable表我:你这个设计有个小问题——这里面没有属于某个服务器而不绑定任何服务的变量
AI:你说得对!💯 我的设计确实遗漏了仅与服务器关联而不绑定特定服务的变量。这是一个很重要的场景,比如服务器的通用路径、特定于服务器的 API Key 等。感谢你的指正!让我把这个层级加进去...
这就是真实的结对编程——AI 给出了一个 80 分的方案,但那漏掉的 20 分正是需要我来补充的。如果没有我对实际使用场景的理解(某些变量确实只和服务器相关,与服务无关),AI 不会主动发现这个问题。
最终我们敲定了四层变量优先级:
服务-服务器变量(最高优先级)
↓
服务器变量
↓
服务变量
↓
全局变量(最低优先级)这个设计的关键洞见是:优先级越高,适用范围越窄。服务-服务器变量只对特定服务在特定服务器上生效,全局变量则对所有服务的所有服务器生效。
这个升级涉及到数据库 Schema 改动、后端 API 改动、前端表单改动……前后花了一周。
4.3 远程部署:告别手动 SCP
MVP 只能把配置文件生成到本地目录,然后我还得手动 scp 到服务器上。这太蠢了。
第二周,我加入了远程部署功能:
- 通过 SSH 连接到目标服务器
- 自动备份原配置文件
- 将新配置写入目标路径
- 可选执行重载命令(如
nginx -s reload)
这个功能用到了 Python 的 paramiko 库。说实话,SSH 连接、密钥认证这些我之前没怎么写过,全靠 AI 帮我搞定。
4.4 前端界面:推翻重做两次
作为后端程序员,我的前端水平可以用"惨不忍睹"来形容。
MVP 的界面是什么样的呢?想象一下:默认的 Element Plus 组件,没有任何样式调整,布局全靠运气……
第一次重做:我让 AI 帮我"美化"界面。结果就是在原来的基础上加了一些 CSS,稍微好看了一点,但还是很"程序员审美"。
第二次重做:我换了个思路,不再说"帮我美化",而是说"参考 xxx(某个我觉得好看的后台管理系统),帮我重新设计"。这次终于像样了。
教训:让 AI 做设计时,给它具体的参考,比给它抽象的描述有效得多。
4.5 边界情况和 Bug 修复
剩下的两周,主要在处理各种边界情况:
- 如果用户删除了一个正在被服务引用的模板怎么办?
- 如果远程部署时 SSH 连接超时怎么办?
- 如果生成的配置文件语法有错误怎么办?
- 如果两个服务用了相同的子域名怎么办?
这些问题 AI 帮不了太多忙——它不知道我的业务逻辑应该怎么处理。这是需要我自己思考和决策的部分。
4.6 一个月后的成果
一个月后,ConfigBridge 的功能基本完善:
- ✅ 四层变量优先级系统
- ✅ 远程部署 + 自动备份
- ✅ 配置版本控制
- ✅ 批量生成和部署
- ✅ 看得过去的前端界面
从新增一个服务需要 30 分钟手动配置,到 3 秒钟一键生成——这就是 ConfigBridge 的价值。
核心功能的详细介绍可以参考上一篇文章,这里不再赘述。
第五章:AI 的高光与低谷
开发过程中,AI 既有让我惊艳的高光时刻,也有让我无奈的低谷时刻。
🌟 高光时刻:SSH 连接代码一气呵成
做远程部署功能时,我对 Python 的 paramiko 库完全陌生。
我只跟 AI 说了需求:"我需要通过 SSH 连接到远程服务器,上传文件,执行命令",它就给我生成了一段完整的代码,包括:
- 密钥认证和密码认证两种方式
- 连接超时处理
- 文件上传(用 SFTP)
- 命令执行和输出捕获
- 异常处理和资源清理
我几乎没改什么就直接用了。这相当于帮我省了至少半天的学习时间。
🔧 实战案例:前后端联调 Bug 排查
这里分享一个真实的 Bug 修复过程。某天我在调试服务详情页面时,控制台突然报了一堆 422 Unprocessable Entity 错误:
Failed to load resource: the server responded with a status of 422
请求失败: services/.../variable-status, 状态码: 422我把日志丢给 AI,对话是这样的:
AI:让我分析一下这个错误。422 通常意味着 FastAPI 在处理请求时数据验证失败。我找到了处理这个路由的代码...问题出在
template_ids: List[UUID] = Body(...)这一行——GET 请求不应该包含请求体,参数应该通过 Query Parameters(就是 URL 里问号后面那一串参数)传递。我:(AI 修改了后端代码后)还是没解决,我把前端报错贴过来...
AI:原来如此!虽然后端改成了接收 Query 参数,但前端代码仍然把
template_ids放在了请求体里。让我查看前端的 API 调用...
接下来 AI 定位到了前端 services.js 文件中的问题:
// 问题代码:函数根本没有接收 template_ids 参数!
export function checkVariableStatus(serviceId, serverId) {
return request.get(`${baseURL}${serviceId}/servers/${serverId}/variable-status`);
}
// 修复后:正确传递查询参数
export function checkVariableStatus(serviceId, serverId, paramsData) {
const config = { params: { template_ids: paramsData.template_ids } };
return request.get(`...variable-status`, config);
}这个 Bug 修复过程展示了 AI 的真正价值:它能快速理解错误日志,定位代码位置,分析问题原因。但也暴露了它的局限——前后端代码分散在不同文件,AI 第一次只修了一半,需要我追问才发现另一半的问题。
低谷时刻:业务逻辑经常失智
但 AI 也有无能为力的时候。
比如:"如果用户删除了一个正在被多个服务引用的模板,应该怎么办?"
我问 AI,它给了我三个选项:
- 禁止删除,提示用户先取消关联
- 级联删除所有关联的服务
- 允许删除,但保留一个"模板已删除"的占位符
这三个选项都是技术上可行的,但哪个是业务上正确的?AI 不知道,因为这取决于我的产品定位和用户预期。
最终我选了第一个:禁止删除,让用户自己决定怎么处理关联的服务。这个决策只能由我来做。
另一个教训:"臆想"出来的方案
还有一次,我让 AI 帮我设计一个新功能的技术方案。结果它写了一整套设计文档,看起来头头是道。
直到我发现——它根本没仔细看现有代码。
它设计的方案里说"需要新增 server_path 字段",但这个字段项目里早就有了。它说"需要修改数据库模型",但现有模型已经支持这个场景。整个方案有一半是在重复造轮子。
我不得不提醒它:"你这个 story 文件完全就是臆想出来的,完全没根据当前项目的情况去设计。"
这件事教会我:AI 需要被"喂"足够的上下文。如果你不主动让它阅读相关代码,它就会基于通用模式去猜测,然后输出一个"看起来正确但脱离实际"的方案。
💡 我的体会
AI 擅长的是:
- 技术问题:报错信息诊断、API 用法查询、代码实现
- 重复劳动:生成样板代码、写 CRUD、调整样式
- 知识检索:它见过无数个类似的问题和解决方案
AI 不擅长的是:
- 业务决策:产品逻辑应该怎么设计
- 架构权衡:这个方案的长期代价是什么
- 上下文理解:它不会主动去了解你的项目现状
最高效的协作方式:我负责思考"做什么"和"为什么",AI 负责帮我"怎么做"。但我也要负责给它足够的上下文,否则它就会"臆想"。
第六章:下一步计划
一个月的开发后,ConfigBridge 的核心功能已经可用。但作为一个自己用的工具,我还有一些想法:
🔮 还想做的功能
| 功能 | 说明 | 优先级 |
|---|---|---|
| 配置语法验证 | 部署前验证 Nginx/FRP 配置语法,避免写错 | 高 |
| Webhook 通知 | 配置变更后自动触发 CI/CD | 中 |
| 多用户支持 | 如果要给团队用的话 | 低 |
| 配置 Diff 对比 | 部署前预览本次变更内容 | 中 |
第六章:关于 AI 结对编程的深度思考
一个月的开发经历让我对 AI 编程有了更深的理解。这里分享几个思考。
🧠 AI 是放大器,不是替代品
很多人问我:"AI 这么厉害,程序员是不是要失业了?"
我的答案是:AI 是放大器,10 倍放大你的能力——但如果你的能力是 0,10 倍之后还是 0。
举个例子:在四层变量设计的讨论中,AI 一开始只给了三层的方案。是我根据实际使用场景发现了遗漏,才最终完善成四层。如果我对配置管理没有任何理解,我根本不会发现这个问题,AI 的"80 分方案"就会直接变成最终方案——然后在实际使用中掉进坑里。
真正的价值在于:
- 你对问题域的理解
- 你对边界情况的敏感度
- 你对用户需求的把握
AI 可以帮你更快地实现想法,但想法本身还得你来。
🔄 "对话"比"指令"更有效
我发现,和 AI 合作最高效的方式不是"下指令",而是"对话"。
低效的方式:"帮我写一个配置管理系统的后端。"
高效的方式:
- "我想做一个配置管理系统,核心问题是...你觉得应该怎么设计?"
- (看 AI 的方案)"这里有个问题...能不能这样改?"
- (继续迭代)"现在开始实现这个模块,但要注意...。"
对话的意义在于:它让 AI 有机会暴露自己的思路,也让你有机会纠正它的错误假设。一开始就全权委托,往往会得到一个"正确但不适合"的结果。
🎯 "上下文工程"是新技能
在这一个月里,我逐渐意识到一个被低估的技能:如何给 AI 提供正确的上下文。
AI 不会主动去读你的所有代码。它读取到的只是你当前对话中提供的信息。如果你想让它给出一个贴合项目现状的方案,你需要主动告诉它:"先看看这几个文件...",或者把关键代码片段直接贴给它。
我把这叫做"上下文工程"(Context Engineering):
- 太少的上下文:AI 会基于通用模式去臆想
- 太多的上下文:AI 会被无关信息干扰
- 恰到好处的上下文:AI 能给出精准贴合的方案
这是一门需要时间摸索的技能。
结语:AI 让我成为"超级个体"
回顾这一个月,我最大的感触是:
AI 没有抢走我的饭碗,反而让我成为了"超级个体"。
如果没有 AI:
- 架构设计可能要花一周时间反复推敲
- 遇到 Alembic(数据库版本工具)这种冷门问题,可能要耗费半天
- 前端 Vue 组件的 CSS 布局,作为后端程序员的我可能要抓瞎
- SSH 远程部署功能,光学 paramiko 库就要花一天
但有了 AI:
- 我负责:提出需求、做出决策、把控质量、提供上下文
- AI 负责:快速实现、填充细节、解决技术卡点、跨越知识壁垒
这不是替代,而是协作。这不是依赖,而是杠杆。
ConfigBridge 只是一个开始。在 AI 编程时代,每个开发者都可以突破自己的技术边界,去实现以前想都不敢想的项目。
你准备好成为"超级个体"了吗?
📌 项目信息
| 项目 | 详情 |
|---|---|
| 项目名称 | ConfigBridge 配置管理系统 |
| 解决问题 | IPv6/IPv4 混合环境下的服务配置集中管理 |
| 技术栈 | FastAPI + Vue 3 + SQLAlchemy + Jinja2 |
| 开发周期 | 72 小时 MVP + 一个月迭代 |
📚 AI开发配置系统系列导航
