Files
server-deploy/docs/2026-09-24-deployment-architecture-review.md
T

295 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 部署架构审查与管理工具接入建议
日期:2026-09-24。状态:历史审查与讨论记录,尚未实施。用户已明确以全新服务器为目标,不需要渐进改造或存量兼容;本文的源码发现仍供参考,涉及保留旧结构、接管与过渡层的建议已撤回。当前候选架构以 [全新部署架构](2026-09-24-greenfield-architecture.md) 为准。
## 1. 范围与结论
本次检查本仓库全部顶层目录、7 份 Compose、共享基础脚本、各工具部署/备份/卸载入口、Gitea/Vaultwarden 升级逻辑、Nginx 模板与已有测试目录。参考项目为 `G:/Works/YouleGames/tools/docker-ops-panel`,检查其文档、连接与身份核验、任务执行、服务清单、会话校验和打包结构。
这是本地源码与架构审查,没有连接生产服务器,没有执行部署、恢复、清理、安装或迁移;不把历史会话的线上结果当作当前生产状态。没有读取实际 `.env` 内容;在普通源码中发现硬编码凭据,本报告不收录其值。
结论:目前应用运行单元已基本分离,主要问题是部署生命周期仍耦合主机环境,缺少稳定的实例身份、操作协议和恢复边界。推荐保留“一工具一独立部署单元”,先规范脚本,再建立可选的本地 SSH 管理面板。无需合并成一份总 Compose,也无需为此引入 Kubernetes。
## 2. 当前目录与运行单元
- `base/`:Docker、Nginx、Certbot、防火墙、系统初始化及共享 Shell 函数;同时承担安装程序和公共库两种职责。
- `gitea/`:独立 Compose,应用 + 私有 MySQL 8.4;含部署、备份、升级、卸载及 Nginx 模板。
- `joplin/`:独立 Compose,应用 + 私有 PostgreSQL;含部署、备份、卸载及 Nginx 模板。
- `vaultwarden/`:独立 Compose,应用持久数据;含部署、备份、升级、卸载及 Nginx 模板。
- `certd/`、`siyuan/`、`portainer/`:各自独立 Compose、数据目录和运维脚本。
- `rustdesk/`:独立 Compose,hbbs + hbbr 组成一个工具,共享该工具的数据目录,包含公网 TCP/UDP 和回环 WebSocket 入口。
- `vps-xray/`:独立 systemd 部署,不使用 Compose;另含内核网络参数、防火墙、定时重启及客户端配置生成。应支持不同主机部署。
- `claude/`:开发机 CLI 配置脚本,不是 Linux 服务器应用栈。
- `claude-dev-stack/`:用户已明确废弃,目录与其中唯一的 `.env` 已从工作区删除,不纳入工具目录、管理界面、适配器或部署计划;历史版本仍保留该文件。
- `docs/`:已有 Xray 设计与测试计划。
- `.claude/`:本地辅助目录,不作为发布单元。
当前 Web 路径为:宿主 Nginx → 各应用的回环映射端口。MySQL/PostgreSQL 没有发布宿主端口。应用之间未发现业务依赖。Gitea SSH、RustDesk TCP/UDP 为公网直达例外。Certd 是独立证书管理应用,当前脚本中的站点证书仍由 Certbot 处理,不能认为 Certd 已接管所有证书。
## 3. 主要发现及证据
### P0:发布内容中存在凭据边界问题
初次审查时 `git ls-files` 确认 `claude-dev-stack/.env` 已被跟踪,随后按用户要求从工作区删除并排除管理范围;`claude/setup-claude-deepseek.sh:14` 和 PowerShell 对应脚本存在硬编码 API 凭据。根 `.gitignore` 中 Xray 生成配置的忽略规则被注释,多个节点信息文件也被跟踪。
新增面板的上传/打包必须使用发布文件白名单,不能递归上传整个工作区。需要另行确认并轮换已进入版本历史的有效凭据,将实际环境文件移出跟踪;仅添加 ignore 不会移除已经跟踪的文件。当前仅按用户要求删除废弃的 claude-dev-stack,不重写历史或轮换密钥。
### P1:应用部署会影响整台主机
`certd/deploy.sh:145` 等应用入口会调用 `init_system`;`base/setup.sh:72` 执行整机 `apt-get upgrade`。应用配置校验在这些步骤之后。Gitea 在自己的脚本里重复了同一套初始化逻辑。
`base/setup.sh:157` 在已有 Docker 配置缺少 registry-mirrors 字段时覆盖整个 daemon.json,随后重启 Docker。应用部署不应隐式执行这些操作。
建议拆分主机初始化、主机维护和应用生命周期;应用只检查基础能力。公共库被 source 时不得隐式安装或修改系统。
### P1:脚本位置依赖阻碍单独分发
Certd、Joplin、Vaultwarden、SiYuan、Portainer、RustDesk 的 deploy.sh 均要求 `../base/setup.sh` 存在,即使服务器已安装所需环境也无法跳过。它们运行时独立,部署包却不独立。
共享源代码可以保留,但单工具发布包应带版本固定的最小运维库,或使用显式安装并验证版本的公共运行器;不能依赖相邻仓库目录。建议先采用发布时打包最小库,减少服务端额外依赖。
### P1:同主机多实例隔离不完整
7 份 Compose 都使用固定 container_name;大部分宿主端口和 Nginx 上游固定。Vaultwarden 虽支持 VAULTWARDEN_PORT,Nginx 模板仍固定 8080。Gitea 升级检测支持 GITEA_HTTP_PORT,但 Compose 和 Nginx 仍固定 3000。
仅设置 Compose 项目名还不够,容器名、端口、数据路径、Nginx 站点名称和备份范围必须同时隔离。项目身份不能只靠当前文件夹名推断。
现有实例应读取 Docker Compose 标签与挂载建立绑定,不应直接删除 container_name 或改项目名后重建;这可能创建第二套容器或误连数据。
### P1:共享入口和证书缺少事务与归属管理
`base/setup.sh:342` 起先把站点替换成临时 HTTP 配置,再申请证书;失败后没有恢复旧站点。`deploy_nginx_conf` 覆盖目标文件后才测试,失败时磁盘上可能留着无效配置。
各工具卸载入口还会删除证书并可能移除共享 Certbot cron。应由独立入口模块持有站点和证书引用,应用卸载只释放自己的绑定;续期调度由环境模块负责。
建议保持宿主 Nginx,使用主机级锁,备份旧配置、生成候选、验证、切换、reload、探测,失败时还原。每张证书只有一个明确的管理者,Certbot 与 Certd 不同时自动修改同一证书。
### P1:备份/恢复契约不足以支撑通用面板
`certd/backup.sh`、`portainer/backup.sh`、`joplin/backup.sh` 等把配置打包错误通过 `|| true` 忽略,随后仍输出成功。多个脚本仅按目录年龄清理备份,缺少成功清单、引用保护与明确的自有文件边界。运行中的数据库/文件目录归档也不能统一视为一致快照。
Gitea 的备份有单独 flock,但 upgrade.sh 没有使用同一把实例锁,不能阻止备份和升级交叠。统一面板锁也必须覆盖 CLI 入口。
恢复应声明类型:配置恢复、镜像回退、数据库恢复、完整快照恢复。数据库迁移不能套用参考面板的通用镜像回退。备份目录需要 manifest、完成标记、文件摘要、版本、数据位置及一致性模式;被回滚点引用的备份禁止自动清理。
### P1:现有升级脚本不应直接视为经过全面验证的执行后端
`gitea/upgrade.sh:617` 附近的 wait_healthy 仍接受任意非 000 HTTP 响应,包括 500。自动和手动回滚忽略 stop 失败后继续恢复数据库,存在写入方未停就恢复数据的风险。自动回滚还可能在服务未就绪后输出“已回滚”。
恢复文件为合并解压,数据库恢复保留新版本额外表;这不等于精确还原。全量备份回灌也会覆盖备份内的 Git 引用文件,不能声称升级后的新提交天然保留。
此前“跨小版本必有 schema 版本增长”“表行数不减少即数据完好”“遗留表普遍无害”都不宜作为所有版本的通用保证。应绑定目标容器、实际数据库、目标版本兼容要求和具体恢复演练;通过有限场景只能证明对应场景。
### P2:非 Docker 工具及端口资源需要单独建模
Xray 默认 XRAY_PORT=443(`vps-xray/deploy.sh:411`),与同一地址上的 Nginx TLS 入口存在绑定冲突的可能;它还执行 sysctl 和防火墙修改。不能把所有工具都抽象成 docker compose up。
面板应支持 Compose 与 systemd 两类执行器;Xray 先支持状态及明确的维护动作。主机网络调优必须作为单独环境计划展示,安装前检查真实监听地址、协议和端口。
### P2:版本、能力、文档存在漂移
多个镜像使用 latest/lts/小版本浮动标签;仓库 Gitea 默认仍为 1.25。根 README 未覆盖 Xray、CLI 工具和残留目录,列出不存在的 gitea/migrate.sh,并把所有端口描述为回环,遗漏实际公网例外。
只有 Gitea/Vaultwarden 有专门 upgrade.sh,其余工具不能仅因存在 deploy.sh 就在面板上显示“安全升级/回滚”。面板应按适配器实际能力显示操作,解析并记录具体镜像 digest。
## 4. 推荐目标架构
采用三层结构,管理界面是可选控制入口:
1. **主机环境**:Docker/Compose、宿主 Nginx、证书续期、防火墙。单独检查、安装、维护,主机级变更说明影响范围。
2. **独立应用实例**:每实例独立 Compose 项目/或 systemd 单元、配置、数据、备份与任务记录。应用私有数据库留在实例内。Gitea 不依赖 Joplin、Certd 或 Portainer。
3. **本地管理面板与 CLI**:共用操作协议和执行器。面板停止后,应用继续工作,已提交的远程任务可以继续并被重新核对。
应用实例目标由 hostId + appId + instanceId + 规范化部署路径 + 实际项目/单元身份组成。所有写计划绑定目标、配置/编排摘要、明确版本、影响资源和恢复能力;执行前在锁内复核。
独立部署应同时满足:只选择一个工具即可准备它自己的依赖;不要求安装其他应用或面板;部署/升级不修改其他应用;独立停启、备份、恢复、卸载;同一台主机可部署第二实例;环境能力缺失时给出独立环境准备计划。
数据库可以在高级配置中外置,但默认不合并共享 MySQL/PostgreSQL;避免将升级、故障和恢复范围扩大到多个工具。
## 5. 管理工具参考项目的取舍
可借鉴的机制:
- React/Vite + Node 本地服务、Windows/macOS 便携启动与打包。
- SSH 私钥/Agent、SHA256 指纹确认,传输层明确区分断线和任务失败。
- 本地 Host/Origin/会话/CSRF 校验。
- 目标绑定与过期预览、配置漂移检查、受控参数、秘密遮蔽。
- 远端任务目录、退出码、日志、进程状态、断线后的状态核对。
- 主机环境操作与应用生命周期分离。
需要重建的业务层:
- `src/contracts.ts:1` 固定了 game-docker 的服务列表。
- `src/connections.ts:388` 会拒绝不存在 game-docker 服务的目录,不能直接连接本仓库的 Gitea/Joplin 部署。
- 部署目录、环境字段、微信/QQ、发布文件清单与业务站点路由均为专用逻辑。
- 现有档案偏向“一个连接目标绑定一个项目”;这里需要“一台主机登记多个独立实例”。
因此建议在本仓库新增 `tools/ops-panel/`,复用经抽取和测试的机制,应用适配器独立定义。不要直接搬整个参考项目再堆条件判断。参考项目自己也将真实 Linux Docker 验收列为未完成,不能把其本地测试当作生产保证。
Portainer 保持可选:它提供容器层管理,本工具负责仓库应用生命周期、备份与恢复计划。直接在 Portainer 修改编排可能造成漂移,面板须检测并要求重新识别。docker.sock 的 `:ro` 挂载不能当作 Docker API 只读权限。
## 6. 候选目录与交付方式
第一阶段保留现有应用目录和线上路径,新增职责明确的目录:
```text
server-deploy/
base/ # 兼容旧入口;逐步成为显式主机环境命令
lib/ # 可版本化、无隐式副作用的通用运维函数
contracts/ # 应用清单、计划、实例、任务、备份 schema
tools/ops-panel/ # 可独立启动的本地管理工具
gitea/ # 原路径保留,逐个添加应用清单与适配入口
joplin/
vaultwarden/
certd/ siyuan/ portainer/ rustdesk/
vps-xray/ # systemd 适配器
claude/ # 开发机配置工具,不默认纳入服务器部署
tests/ # 协议、脚本故障、真实隔离验收
docs/
```
应用清单声明:标识/版本、运行器、Compose 服务角色、环境要求、端口及入口、秘密字段、数据挂载、健康探测、升级与恢复策略、支持的动作。清单不是任意命令执行接口,执行器仍使用受控命令和参数校验。
远端先保持 `/opt/gitea` 等既有目录;已有数据路径按真实挂载登记。新实例可采用 `/opt/selfhost/instances/<实例>/`、`/var/lib/selfhost/<实例>/` 和 `/var/backups/selfhost/<实例>/`,但不自动移动旧目录。单工具发布包只包含自身清单、Compose、脚本/模板和所需版本的通用库,避免依赖整仓库。
## 7. 方案比较与实施顺序
**推荐:独立应用 + 共享环境 + 本地 SSH 面板。** 最接近当前结构,改造可以逐工具进行,日常运维不依赖服务器额外常驻控制服务。
**备选:独立应用 + 服务器 Web 面板。** 适合多人协作,但增加集中凭据、用户权限、审计、HTTPS 和面板自身可用性的维护成本。
**不推荐:全服务合并 Compose,通过 profiles 选择。** 能集中启动,却容易重新引入共享环境、项目级操作和恢复范围耦合,不符合本次强调的独立部署目标。
建议实施顺序:
1. 凭据与发布边界清理;明确环境与应用责任;登记所有已有实例,不重建容器。
2. 固化实例/任务/备份协议;统一实例锁及主机环境锁,应用配置校验先于所有修改。
3. 选择无外部数据库的 SiYuan 做独立部署试点,验证端口参数、反代、数据保留、多实例及失败恢复。
4. 建立面板只读版:多主机、多实例、状态、日志、配置脱敏、备份目录和任务核对。
5. 接入经过验收的部署/配置更新/备份动作;Gitea、Vaultwarden、Joplin 各自定义迁移与恢复策略。
6. 单独接入主机环境维护、Xray;按需扩展 Certd 与 Portainer。
升级应选择明确目标版本;预览可以查询新版本,但确认后的执行不能重新解析 latest。取消选择工具只表示本次不操作,不能转换为卸载。卸载默认保留数据,销毁数据是独立动作。
## 8. 验收边界
- 只拿单个工具发布包,在准备好的环境中完成部署;同机启动第二实例且端口、数据、路由不交叉。
- 面板或 SSH 断开后,远程任务可以核对,不自动重发有副作用的步骤。
- 部署单个工具时,其他工具容器 ID、挂载、配置与运行状态不发生非预期变化。
- backup/upgrade/restore/uninstall 共用锁;公共环境维护与应用变更互斥。
- 镜像拉取失败、磁盘不足、数据库未就绪、配置漂移、Nginx 校验失败,均有明确阶段和退出状态。
- 停机失败时禁止恢复数据库;备份失败禁止继续迁移;恢复失败明确进入需人工检查,不输出成功。
- 恢复既验证归档也实际恢复数据库/仓库,并核验应用功能;数据行数只是辅助证据。
- 保留现有数据路径、镜像和回滚资料;接管只建立基线,执行迁移另有计划。
## 9. UI 方向(用户已确认)
管理工具采用 Apple 风格,参考 macOS 原生工具的信息组织与交互节奏。此项是视觉与交互要求,不意味着必须改用 Swift、Electron 或其他桌面框架,也不等同于已选择本地或服务端部署形态。
- **整体视觉**:中性背景、克制的蓝色强调、清晰字体层级、充足留白、适度圆角与轻分隔。避免大面积渐变、过度毛玻璃和满屏同质卡片。
- **主框架**:侧边栏负责导航;顶部持续显示当前服务器、环境与应用实例;内容区按概览、应用、环境、任务和备份组织。切换目标后清除旧预览,避免操作到上一台服务器。
- **应用列表**:优先用紧凑列表展示名称、版本、状态和入口;详情页提供配置、日志、备份与升级等能力,未支持的动作不伪装成可用功能。
- **操作流程**:部署按“选择工具 → 配置 → 预检与变更预览 → 执行结果”推进。配置采用分组表单,长任务使用明确的阶段和可展开日志,保留任务恢复入口。
- **生产操作**:预览明确展示目标、影响的实例、预计停机及数据恢复范围;危险动作使用独立且具体的确认。颜色辅助提示,不能代替文字说明。
- **可访问性**:键盘焦点可见、文本对比度充足、状态不只依靠颜色;以系统字体栈适配 Windows/macOS,不分发 Apple 专有字体资源。
下一步设计应先明确页面结构与核心流程,再制作少量关键页面原型;当前尚未实现 UI。
## 10. 官方参考
- Compose 项目命名与隔离:https://docs.docker.com/compose/how-tos/project-name/
- Compose 默认网络:https://docs.docker.com/compose/how-tos/networking/
- 服务定义与 container_name:https://docs.docker.com/reference/compose-file/services/
- Docker daemon 权限:https://docs.docker.com/engine/security/
- SSH 保护 Docker 访问:https://docs.docker.com/engine/security/protect-access/
待确认的产品选择:管理工具是本地 SSH 面板还是服务器 Web 平台。本文优先推荐前者;选择后再形成实施规格与任务拆分。
## 11. 第二轮评估:收敛为可实施的结构
### 11.1 判断与纠偏
第一版对独立应用、共享环境、渐进接管的方向判断成立,但仍不足以作为直接开发的架构规格:执行责任不明确,容易让 Node、CLI、Shell 各自实现一遍操作;对多实例、外部数据库、双入口提供者等扩展的优先级偏高;UI 罗列功能而没有明确使用层级。
现代化的衡量标准是可复现、声明清楚、可观测、失败可判定、模块可独立测试,而不是增加框架、微服务或自动发现组件。本项目适合模块化单体管理工具 + 独立应用发布包 + 明确的环境模块。
### 11.2 独立部署的实际边界
首版必须保证每个工具能单独安装、停启、升级和备份,不依赖其他业务应用及面板在线。共享 Docker、入口和系统资源意味着仍有共同故障域,不能承诺同主机上的绝对故障隔离。
同主机多实例作为架构约束预留(独立身份、参数化资源),先在试点应用验证;不要求首版所有工具完成多实例 UI 和复杂迁移。外部数据库作为未来扩展,不在首版同时支持所有组合。
Gitea + 私有 MySQL、Joplin + 私有 PostgreSQL、RustDesk 两组件分别是一个部署单元。应用镜像更新与其数据库引擎升级是不同操作,不能因全栈 pull 顺带升级数据库。
应用包只声明所需环境与入口,不负责无条件安装 Nginx、签发证书或重启 Docker。入口模式至少在模型中区分“受管入口”“外部入口”“仅内网”,实际支持范围由适配器声明;应用自身要求公网 HTTPS 时仍需阻止不满足要求的配置。
### 11.3 入口方案与部署合理性
当前改造基线继续使用宿主 Nginx + Certbot:保留既有证书、站点和路径,集中到环境模块管理,避免与应用迁移同时更换网关。每台主机的监听地址和端口必须有明确归属,应用只申请自己的路由。
Caddy 的自动 HTTPS 可以减少新服务器的证书管理代码,是合理的后续选择;但它不自动解决既有 Nginx 路由、特殊长连接、证书接管和端口迁移。因此首版不同时实现两套网关,不强迫存量服务切换。入口操作接口应保持小而具体:检查、规划站点、应用站点、验证、移除本站点绑定。
容器化网关也可行,但不能把所有数据库加入公共代理网络。若未来改用容器网关,需单独设计前端网络与应用私有网络。当前回环端口 + 宿主代理在此规模下足够清楚。
### 11.4 管理工具采用模块化单体
候选仍为 React + TypeScript 前端及一个 Node 本地服务;技术版本在实施时锁定。首版不引入微服务、独立消息队列、常驻远端 Agent、插件市场或 Electron/Tauri 外壳。
面板内部按职责组织,而不是持续扩大一个 operations.ts:
```text
tools/ops-panel/src/
domain/ # Host、AppDefinition、Instance、Plan、Operation、Backup
application/ # 发现、接管、预览、执行、核对等用例
infrastructure/ # SSH/SFTP、存储、应用目录读取
http/ # 本地会话、校验、API、任务事件
web/
app/ # 路由、当前目标、整体布局
features/ # 服务器、应用实例、任务、设置
ui/ # 基础组件与设计 token
```
依赖方向为 UI/API → 用例 → 领域模型;用例通过小接口使用 SSH 和存储实现。领域模型不依赖 React、HTTP 或 SSH。不要为每个目录强建独立 npm 包;出现第二个真实消费者时再提取公共包。
主机档案与应用实例分开:一台主机有多个实例;应用定义描述模板和能力,实例记录具体路径、配置引用和现场身份。Plan 表示有时效的目标变更;Operation 表示一次执行;Backup 表示可验证的恢复资料。不要把这些全部塞进一个不断扩展的 ServerProfile。
### 11.5 单一执行入口,避免三套实现
前端负责输入、预览和展示;本地服务负责连接、调用用例与核对任务;远端版本化运行器负责现场检查、实例锁、执行步骤和结果记录。应用适配器提供真正有差异的备份、迁移、健康验证及恢复步骤。
GUI 与服务器上的 CLI 都调用同一个远端执行入口。旧 deploy.sh/backup.sh/upgrade.sh 在逐项验收后才改成兼容入口;不新增一套 TypeScript Shell 字符串流程与原脚本并行维护。
目标流程:发现/检查 → 生成计划 → 展示变更 → 确认 → 锁内重验 → 执行 → 验证 → 记录结果。远端运行器不成为常驻服务;每个任务保留固定版本代码、计划标识、实例身份、阶段日志和退出状态,SSH 断线后继续运行或进入明确的待核对状态。
任务结果必须区分:成功、失败且已恢复、失败需处理、结果待核对。不能将网络断开直接标记为失败或自动重试,也不能把“发出恢复命令”当作“已恢复”。中断恢复指核对现场和受控续做,不代表每个 Shell 步骤都能从中间续跑。
首版同主机写任务串行、跨主机可并行,读取不取写锁;CLI 使用相同锁约定。后续证明有必要时才细分实例并行锁与环境排他锁,避免过早设计复杂调度器。手工操作及 Portainer 不会自动遵守本工具的锁,因此执行前仍要核对配置与现场漂移。
### 11.6 单一事实来源与分发
应用目录内的清单是该工具字段、能力和运行入口的唯一声明来源;Compose 是容器编排来源。面板不再手写第二套服务列表或镜像默认值。旧实例以实际挂载与项目标签建立记录,不由新模板覆盖现场。
发布时产出独立、版本化的应用包,包含本应用定义、Compose/模板、适配步骤与固定版本的最小运行器。源代码共享,发布包自包含;更新管理面板不隐式更新服务器应用包。
版本需区分面板版本、应用包版本、运行器协议版本和上游镜像 digest。计划锁定具体包与镜像;包摘要只证明内容一致,若要防范供应链替换还需要可信发布来源或签名,不能将普通 checksum 当作来源认证。
本地保存主机档案和任务索引,远端任务结果是执行核对依据。首版可以用经串行化和原子写入的 JSON 文件存储小规模元数据;不为几台服务器强加本地数据库。通过 Store 接口隔离,确有查询、规模或事务需求时再换 SQLite。秘密不进入任务摘要、前端持久存储或普通日志。
### 11.7 Apple 风格落实到信息架构
全局导航保持简洁:服务器、任务、设置。进入服务器后显示其应用实例与独立的运行环境页;“添加应用”进入工具目录。实例详情再提供概览、配置、日志、备份与版本历史,避免把每个动作升级为全局导航项。
常用操作贴近当前对象:重启在实例工具栏,升级在版本信息附近,恢复从具体备份进入。预览使用稳定的页面或侧栏,只对真正需要确认的影响做确认,不层层叠弹窗。任务状态与阶段、日志分开,真实可计算时才展示百分比。
视觉采用中性色、统一字级和间距、小面积状态色、系统字体、清楚的选中与焦点状态;适量材质不妨碍日志阅读。Apple 风格是一致性、层级和反馈,不是简单地增加圆角或玻璃背景。离线显示最后更新时间与“状态未确认”,不把历史绿色状态当作当前健康。
### 11.8 缩小首版并调整交付方式
第一条闭环采用一个应用:应用包 → 独立 CLI → 面板识别 → 部署预览 → 执行 → 健康验证 → 备份/恢复演练。完成后接入第二个带数据库的应用,验证抽象是否成立,再批量扩展。
这比先重写全部脚本、再开发一个大型面板更容易发现协议设计问题。共享环境准备作为单独入口随试点一起提供,但 Docker 版本升级、证书提供者切换、所有工具多实例和外部数据库组合不同时纳入首版。
验收应覆盖:只分发单工具包、另一应用持续正常、断线后任务核对、停机失败拒绝恢复、备份失败阻止迁移、失败结果真实、已有实例原路径接管。UI 原型与领域接口可以先设计,但本节仍是评估后的建议,未开始应用代码实现。
补充官方参考:Caddy 自动 HTTPS https://caddyserver.com/docs/automatic-https 。其能力说明不构成对当前生产网关切换的建议。