Files
server-deploy/docs/2026-09-24-greenfield-architecture.md

156 lines
11 KiB
Markdown
Raw Permalink 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。状态:候选设计,待评审,不代表实现完成。
## 1. 已确认的约束
- 为全新服务器设计;不保留旧部署目录、脚本接口或迁移兼容层。
- 工具可以独立部署,公共环境可以共享;管理面板不是应用运行依赖。
- 优先考虑职责清晰、设计一致、可复现及数据保护。
- UI 采用 Apple 风格。
- claude-dev-stack 已废弃,不进入新设计。
本文取代旧审查报告中以渐进兼容为前提的建议。完整架构统一设计;工程实施仍需分模块验证,不等于维持两代部署体系。
## 2. 总体选择
推荐本地 React/TypeScript 管理面板 + Node 本地 API,通过 SSH 调用 Linux 上的单一运维执行器。执行器建议用 Go 编译为独立 CLI 二进制,以避免远端 Node 依赖和大规模 Shell 字符串拼接;代价是仓库需维护 TypeScript 与 Go 两种语言及对应测试。
公共环境包括 Docker Engine/Compose、宿主 Caddy、systemd 与必要的主机准备。Caddy 负责反向代理和自动 HTTPS;默认不再安装 Nginx + Certbot,不再由应用写续期 cron。DNS、证书签发可达性与云安全组仍需实际校验。
应用采用各自独立的 Compose 项目。Xray 采用 systemd 适配器,保持适合其运行方式的部署。没有总 Compose,也没有跨业务应用共享数据库。
本地面板形态是推荐选择,用户尚未明确指定运行位置;若选服务器 Web 平台,认证、凭据存储与多用户边界需要另行设计,但应用包和执行器协议保持相同。
## 3. 服务器布局与职责
```text
/usr/local/bin/deployctl 唯一 CLI 入口
/opt/server-deploy/packages/<id>/<ver>/ 只读、版本化应用包与校验信息
/etc/server-deploy/ 主机配置、实例声明、秘密引用
/var/lib/server-deploy/ 实例登记、任务状态、应用持久数据
/var/backups/server-deploy/<instance>/ 备份集与恢复清单
/etc/caddy/ 受管网关配置
```
具体子路径由实例 ID 生成并校验,不允许用户输入直接成为任意写入/删除目标。应用包与可变数据分离;更新包不覆盖数据目录。秘密文件使用严格文件权限并从备份与日志展示中脱敏。
Gitea + MySQL、Joplin + PostgreSQL、RustDesk hbbs + hbbr 分别作为一个应用单元。它们的数据库/配套组件有明确角色,应用镜像升级不默认更新数据库引擎。
Compose 项目名由实例 ID 固定生成,不使用固定 container_name。同一工具的不同实例拥有不同配置、挂载、端口、项目网络和备份目录;多实例是统一模型的一部分,不依靠复制脚本修改名称。
## 4. 入口与网络
选择宿主 systemd 管理的 Caddy,HTTP 应用只向宿主回环地址发布端口,Caddy 转发到对应端口。该方案使网关不依赖 Docker socket,也不需要将不同应用的数据库放进公共网络。
端口由执行器分配、登记并在执行前检查占用,不能每次启动随机变化。应用对外 URL、Compose 映射和网关上游都来自同一份实例配置。计划阶段的可用端口检查不消除抢占竞争,绑定失败仍必须作为可恢复错误处理。
每个应用的数据库只连接本项目网络,不发布宿主端口。Compose 项目隔离不是对同一 Docker daemon 的强安全隔离;有高权限 Docker 访问的主体仍可跨项目操作。
Gitea SSH、RustDesk TCP/UDP、Xray 是协议直达入口,单独声明监听地址、端口、协议及防火墙要求。Xray 与 HTTPS 网关不能同时绑定同一地址的 TCP 443;部署规划应拒绝冲突,或明确使用不同端口/IP/主机。
网关变更由唯一入口模块管理:收集已登记路由 → 生成候选配置 → 校验 → 切换并 reload → 访问验证。失败保留旧配置及诊断。证书状态和持久数据独立保存;删除一个应用不得删除其他应用的证书或共享网关。
Certd 保留为可选的独立工具,用于额外证书工作流;不自动管理 Caddy 已负责的证书。Portainer 同样可选,属于高权限容器管理入口,不是本工具的依赖。
## 5. 应用包与单一事实来源
每个应用包包含:
- 版本化清单:参数类型、秘密标记、组件角色、入口与数据位置、支持动作。
- Compose 模板或 systemd 模板。
- 版本锁:明确的上游版本和平台对应镜像 digest。
- 应用特有的备份、迁移与验证策略声明。
- 协议版本、文件清单和完整性摘要。
声明以可校验的数据表达,不能退化为任意远程命令字段。复杂恢复由内置且经过测试的应用适配器处理;不为简单需求创造通用工作流编程语言。
面板表单和能力显示读取应用清单,不手写第二份服务列表。应用包发布与面板发布解耦;执行器在预检中校验应用包协议兼容性。校验和验证内容一致性,可信分发还需可信来源/发布签名。
只分发一个应用包及兼容的 deployctl,就应能在准备好的主机上通过 CLI 部署该工具。公共环境初始化是独立命令,应用部署只检查环境或生成明确的环境准备计划,不隐式整机升级。
## 6. 唯一运维执行器
deployctl 同时服务本机 CLI 与 SSH 调用,承担现场检查、规划、互斥锁、执行、健康验证及结果记录。面板后端不再生成另一套安装/回滚脚本;GUI 与 CLI 的业务操作经过同一执行路径。
协议使用版本化 JSON 请求/响应及阶段事件,应用核心不依赖终端彩色输出。参数作为独立进程参数传递,避免经过 shell 二次解释;日志统一脱敏。高权限操作只在明确的主机维护或应用执行路径发生。
远程任务通过 systemd 管理的任务单元脱离 SSH 会话,执行固定版本程序。持久记录 operation ID、计划摘要、目标身份、运行阶段及退出状态。机器重启后先核对现场,不假设数据库迁移可以自动从任意位置续跑。
操作顺序为:inspect → plan → approve → apply → verify。apply 在锁内重验计划条件;过期、配置变化、版本变化时要求重新规划。同一主机写任务先统一串行,跨主机可并行,读取独立执行;后续若需要并发,可在保持接口不变的前提下细分锁范围。
结果明确区分成功、失败已恢复、失败需处理、状态待核对。恢复数据库前必须确认写入方已停止。镜像回退、配置恢复、数据恢复是不同动作,不承诺统一“回滚一切”。
备份包含完成标志、源实例、版本、内容摘要、一致性模式与恢复要求;归档通过校验不等于恢复演练通过。恢复覆盖升级后数据的风险必须出现在计划中。被恢复点引用的备份禁止自动清理。
## 7. 管理工具结构
管理工具为一个模块化单体,前后端随一个便携产品发布:
```text
apps/ops-panel/
src/domain/ 主机、定义、实例、计划、任务、备份
src/application/ 主机连接、应用目录、计划确认、任务核对
src/infrastructure/ SSH/SFTP、应用包仓库、存储
src/http/ 本地会话、API、任务事件
src/web/app/ 布局、路由与当前目标
src/web/features/ 服务器、实例、任务、设置
src/web/ui/ 组件和设计 token
```
前端不直接执行命令;HTTP 层不实现部署逻辑;连接模块不识别具体 Gitea 字段;领域模型不依赖 React 或 SSH。远端执行器是操作结果的权威来源,本地保存连接档案、用户偏好和任务索引。
本地持久化采用 SQLite,适合关联主机/实例/计划/任务、执行记录查询及事务写入;它是嵌入式文件,不引入额外数据库服务。具体驱动需结合便携 Node 运行时验证。SSH 优先使用 Agent/本地私钥引用,数据库中不保存私钥内容。
本地服务只监听回环地址,保留 Host/Origin、会话及 CSRF 校验。面板关闭不影响应用和远程任务;重新打开后按任务 ID 核对结果。
## 8. 新仓库目录
```text
server-deploy/
apps/ops-panel/ 本地管理产品
cmd/deployctl/ Go CLI 入口
internal/ 执行器内部模块
planner/
executor/
state/
runtime/ compose、systemd、gateway 适配
applications/ 必要的应用专有策略
catalog/ gitea、joplin、vaultwarden 等版本化应用包源
platform/ Docker、Caddy、主机初始化与维护定义
protocol/ 请求、计划、事件及清单的 schema
scripts/ 构建、发布、打包;不承载另一套运维业务
tests/ 协议一致性、隔离端到端、故障与恢复验收
docs/ 架构决策、操作说明和应用恢复边界
```
catalog 放部署对象,apps 放管理产品,platform 放公共环境,执行逻辑集中在 deployctl。旧顶层工具目录不作为兼容结构保留;实际重组在设计批准后的实施中完成,不能把设计文档新增解释为已完成重构。
## 9. Apple 风格与信息结构
主导航:服务器、任务、设置。服务器详情下分应用实例与运行环境;添加应用打开应用目录。实例详情提供概览、配置、日志、备份和版本历史,操作位于具体对象附近。
采用清晰留白、统一字级/圆角/间距、克制的状态色、系统字体、键盘操作、深浅色主题和可访问焦点。日志区域强调密度与可读性,不套用大面积玻璃材质。任务阶段与日志分离;离线状态显示最后核对时间。
部署以明确目标和差异预览为中心;默认值来自应用包,高级项逐步展开。需要数据恢复或停机的操作显示具体范围,不用重复弹窗代替设计清晰的操作流程。
## 10. 设计质量的验收标准
- 新增常规 Compose 应用主要增加 catalog 定义,而非修改 UI/连接/任务核心。
- GUI 与 CLI 对同一请求产生相同现场计划和执行结果。
- 应用 A 升级不变更应用 B 的配置、数据库、数据或镜像。
- 同工具多实例的项目名、端口、数据和入口从配置生成,无手工改源码。
- 面板失联、SSH 中断、磁盘不足、镜像不可用、停机失败和恢复失败均有可核对结果。
- Caddy、数据库及应用数据有明确所有者与备份边界。
- 模板、协议、执行器和界面有自动测试;真实隔离服务器覆盖部署、升级、备份及恢复。
共享主机仍有共同故障域。本方案提供生命周期和资源归属隔离,不声称达到多租户强隔离或多节点高可用。
## 官方依据
- Caddy 自动 HTTPS:https://caddyserver.com/docs/automatic-https
- Compose 项目身份:https://docs.docker.com/compose/how-tos/project-name/
- systemd transient services:https://www.freedesktop.org/software/systemd/man/latest/systemd-run.html
待评审:本地面板运行形态、Go 单二进制执行器以及统一 Caddy 入口均为本方案的明确推荐,尚未视为用户逐项批准的实现选型。