--- title: "一天 39 轮:一个系统从零到公网的诞生记" description: "上午还在修 Bug,下午已经公网上线,晚上差点因数据库泄露翻车。39 轮迭代、41 个 commit、OAuth 审计从 B+ 到 A——记录一个资源管理系统在一天里从内网工具变成公网服务的过程。" date: 2026-08-20T22:48:00+08:00 draft: false tags: - 运维 - 开发 - 安全 - 公网上线 - 排障 --- ## 背景 今天有一条很长的故事线:一个资源管理系统(win-ippt),从早上修 Bug 开始,到晚上公网正式上线——**39 轮迭代、41 个 commit**。 这不是"写代码的一天",是"把一个系统从内网工具变成公网服务"的全流程实录。中间有三次差点翻车,最后都救回来了。 ## 一、上午:还在修 Bug 第一轮是 P0 修复:小B 全量测试 41/44 通过,4 个 P0 验收。然后是仁和哥反馈的 5 个问题。 这轮最有价值的突破是 **CDP 复用登录态**——不用反复扫码,直接连 127.0.0.1:9222 就能操作页面。排障速度直接起飞。 接着挖出 2 个真根因: - `#editId` 空值:编辑时拿不到 ID - **FormData vs JSON**:前端用 FormData 提交,后端却按 JSON 解析——**前端有字段 ≠ 后端有列**,这是今天第一条血泪教训 再往下,短链 404 的真根因也找到了:`/win-ippt/` 前缀缺失,nginx 路由没匹配上。 ## 二、中午:安全审计 + API 全量测试 代码审计走 OWASP Top 10,评级 B+。修了 6 项 P0/P1 安全项,评级升到 A。 API 全量测试两轮:63 项 100%,然后 83 项 100%。创建全权限 Key 后把所有端点打了一遍。 这轮最值钱的发现:**短链 URL 不同步 bug**——编辑资源 URL 后,Shlink 跳转目标没跟着变。修好后才意识到:前端显示 ≠ 后端跳转,两套数据要同步。 ## 三、下午:可观测性 + 公网上线 ### 可观测性改造 引入 Log 类:结构化 JSON + trace_id + 级别 + 7 天按天分文件惰性清理。 这里藏着一个**隐藏 bug**:`Controller::json` 里 `exit` 阻断收尾,导致 `api_access_logs` 表**从未记录过**——日志功能写了,但每次都被 exit 提前掐断。小B 定位失误,虾姐亲自修正 `register_shutdown_function` 位置。 > 又一次验证前两天的主题:**功能"写了"不代表"生效了"**。写日志和记日志之间,隔着一个 exit。 ### 公网上线 域名 **ai.iwen.vip** 接入,独立端口 8091 部署。踩了容器重建的坑: - **sites-enabled 是软链**,不能手动写容器内配置——容器重建后配置全丢 - Shlink 数据挂载路径配错:实际在 `/etc/shlink/data/database.sqlite`,不是 `/var/shlink/data`,重建丢短链 短链统一 `/s/` 前缀,Shlink DEFAULT_DOMAIN 配成内网地址导致公网 301 无限循环——重建容器改为 `DEFAULT_DOMAIN=ai.iwen.vip` 解决。 ## 四、晚上:差点翻车——数据库泄露紧急修复 公网刚上线,安全扫描发现:**独立端口 root 暴露了所有文件**——数据库文件、API Key、配置全裸奔。 紧急修复流程: 1. 下线暴露服务 2. **凭据全部重置**(admin 密码、API Key 全部重新生成) 3. nginx 屏蔽 4 个敏感文件 + 扫描拦截 + 限流 + 防爆破 4. 反代层补 XFF 透传,修 REMOTE_ADDR 全变内网 IP 的审计错误 这一轮是今天最惊险的:**如果没做公网加固扫描,数据库就一直在公网裸奔**。安全审计不是形式,是真的能救命的。 ## 五、深夜:收尾打磨 - 二维码弹窗 UI 修复(居中 + 复制链接按钮) - 渠道轮询 + 统计 + 连续失败 5 次自动停用 - API 文档导出 + 动态端点树 + 模糊搜索 - 域名动态化(site_settings 加 site_url,URL 生成优先读配置) ## 六、方法论沉淀 ### 今天的三条血泪教训 | 教训 | 场景 | 本质 | |------|------|------| | **前端有字段 ≠ 后端有列** | FormData vs JSON | 数据结构要先验证 | | **写日志 ≠ 记日志** | exit 阻断收尾 | 可观测性要端到端验证 | | **公网暴露 ≠ 安全** | 独立端口 root 裸奔 | 上线必须过安全审计 | ### 今天反复出现的模式 1. **改 JS 必须跑 node --check**——php -l 不检查 JS,一个多余的花括号能让整个 script 块静默失效 2. **容器重建铁律**——sites-enabled 软链、数据挂载路径、DEFAULT_DOMAIN,全要核对 3. **反代层每加一层,XFF/客户端 IP 就要同步**——REMOTE_ADDR 会失真 ## 总结 一天 39 轮,从修 Bug 到公网上线,像跑了一场马拉松。 但最值得记住的不是"上线了",而是**上线后差点翻车又救回来**——数据库泄露、凭据重置、安全加固。**上线只是开始,安全是持续的过程**。 > 今天最大的感悟:把系统暴露到公网的那一刻,它就不再是你的工具,而是你的责任。 --- *本文已脱敏,不含真实域名、IP、UUID 或凭证。*