Skip to content

Commit 560309d

Browse files
committed
docs(research): 记录三平台远程装机方案
1 parent e1dbd2a commit 560309d

7 files changed

Lines changed: 566 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# 远程装机与多仓库集成设计
2+
3+
## 1. 架构边界
4+
5+
方案由三个独立 Git 仓库组成:
6+
7+
| 仓库 | 权威来源 | 职责 |
8+
|---|---|---|
9+
| `powershellScripts` | GitHub 公开仓库 | 跨平台 Stage 0/Stage 1、远程安全入口、平台验证与公共文档 |
10+
| `self-hosted-compose` | macmini Forgejo 私有仓库 | Ansible control plane、inventory、主机差异、连接 bootstrap、执行编排与状态汇总 |
11+
| `powershellScripts-secrets` | macmini Forgejo 用户私有仓库 | 明文管理员密码、Token 等实际凭据;不保存 SSH 私钥 |
12+
13+
GitHub 是 `powershellScripts` 的唯一权威源。现有 Forgejo pull mirror 只保留为周期性备份,不参与发布、Ansible 版本选择或 submodule URL 解析。
14+
15+
## 2. Submodule 设计
16+
17+
`self-hosted-compose` 在以下路径引入公开 GitHub 仓库:
18+
19+
```text
20+
reference/powershellScripts
21+
```
22+
23+
`.gitmodules` 使用公开 URL:
24+
25+
```text
26+
https://github.com/mudssky/powershellScripts.git
27+
```
28+
29+
父仓库固定一个 GitHub 已存在的 commit。submodule 主要用于:
30+
31+
- agent 在 `self-hosted-compose` 工作区内同时读取安装编排和平台脚本。
32+
- Ansible role 在控制端读取固定版本的公共脚本、入口和验证合同。
33+
- 父仓库通过 gitlink 明确记录本次运维代码依赖的 `powershellScripts` 版本。
34+
35+
父仓库不拥有子仓库源码。对子仓库的修改必须先在 `powershellScripts` 独立验证、提交并推送 GitHub,再在父仓库更新 gitlink。
36+
37+
### 工程规范适配
38+
39+
沿用 `self-hosted-compose` 既有 pnpm workspace、Biome、Prettier、Husky 和 Trellis 配置,不复制 `project-standards` 的完整 submodule-host 模板。
40+
41+
只补以下缺口:
42+
43+
- 根 `package.json` 增加 `submodules:status`、`submodules:update`、`submodules:pull`。
44+
- `biome.json` 和 `.prettierignore` 排除 `reference/powershellScripts`。
45+
- 根 README/AGENTS 记录父子仓库边界、初始化、更新和提交顺序。
46+
- 不把 submodule 纳入 `pnpm-workspace.yaml` 的 `apps/*`。
47+
- 首版不修改 `.trellis/config.yaml` 的 package 模式,避免把现有 single-repo spec 层级意外切换为 monorepo package scope。
48+
- 不增加 `submodules:push`:父仓库将子模块视为 GitHub 上的只读依赖,不能从父仓库递归推送子仓库提交。
49+
50+
## 3. Ansible Control Plane
51+
52+
复用 `self-hosted-compose/deployments/ansible`,不在公开仓库复制第二套 inventory 和 Ansible 配置。
53+
54+
目录扩展方向:
55+
56+
```text
57+
deployments/ansible/
58+
├── inventories/homelab/
59+
├── playbooks/
60+
│ ├── workstation-bootstrap.yml
61+
│ ├── workstation-provision.yml
62+
│ └── workstation-verify.yml
63+
└── roles/
64+
├── workstation_common/
65+
├── powershell_scripts/
66+
└── windows_psrp_bootstrap/
67+
```
68+
69+
职责:
70+
71+
- inventory 保存主机名、平台分组、Tailscale 地址、目标用户和非敏感策略。
72+
- secrets 仓库提供实际密码和 Token,通过控制端本地路径加载。
73+
- role 读取 submodule 中的安装入口与脚本,不复制包清单或平台步骤图。
74+
- 默认只执行连接检查、计划和 `WhatIf`;真实安装必须显式指定 `--limit` 与 apply 开关。
75+
76+
## 4. 控制端矩阵
77+
78+
| 控制端 | 运行方式 |
79+
|---|---|
80+
| Linux | 原生 Python/Ansible;支持通过 VS Code Remote SSH 手动执行 |
81+
| macOS | 原生 Python/Ansible |
82+
| Windows | WSL2 Ubuntu 内运行,不支持原生 Windows control node |
83+
84+
所有控制端 clone `self-hosted-compose` 并初始化公开 submodule;需要真实执行时再 clone 私有 secrets 仓库到约定的本地路径。
85+
86+
## 5. 被控端流程
87+
88+
### Linux/macOS
89+
90+
1. 使用 SSH 连接。
91+
2. 验证平台、架构、sudo 和 Tailscale 基线。
92+
3. clone/更新公开 `powershellScripts` 到目标用户目录。
93+
4. 调用现有平台 Stage 0/Stage 1。
94+
5. 首期以 `Core` 为强验收;`Full` 为显式可选。
95+
6. 调用平台 `99` 验证入口并收集结构化结果。
96+
97+
### Windows
98+
99+
1. 前置条件:Windows 已安装、Tailscale 已连接、管理员 OpenSSH 可登录。
100+
2. 通过 OpenSSH 下发固定 PowerShell bootstrap。
101+
3. 创建自签名证书和 HTTPS PSRP listener,端口 `5986`,仅绑定当前 Tailscale IP。
102+
4. 保留现有 Windows 防火墙全局状态;启用时增加 Tailscale scoped rule,关闭时验证 LAN/Wi-Fi 未监听 `5986`。
103+
5. 验证 PSRP `win_ping` 后切换正式连接。
104+
6. 管理员机器阶段安装 Git、PowerShell 7 和可选机器组件;不依赖 UAC 可见窗口。
105+
7. 必要时使用 `win_reboot` 重启并等待 PSRP 恢复。
106+
8. 普通用户阶段执行 Scoop、Profile、根 Stage 1 和 JSON 验证。
107+
108+
## 6. Secrets 集成
109+
110+
`powershellScripts-secrets` 是独立 Forgejo 用户私有仓库,不作为 submodule,避免在公开配置或 `.gitmodules` 中传播私有 URL。
111+
112+
建议结构:
113+
114+
```text
115+
inventories/homelab/
116+
├── group_vars/
117+
│ └── windows.yml
118+
└── host_vars/
119+
└── <host>.yml
120+
```
121+
122+
允许按现有私有 Forgejo风险模型保存管理员密码和 Token;禁止保存 SSH 私钥。每个控制端独立生成 SSH 私钥,secrets 仓库只保存公钥/授权声明。
123+
124+
主仓库通过环境变量或忽略的本地配置解析 secrets checkout 位置,不提交绝对路径。加载前校验目录存在、Git remote 指向预期私有 Forgejo、工作树无意外未提交明文变更。
125+
126+
## 7. 安全与失败语义
127+
128+
- 默认 plan/check,不默认修改真实主机。
129+
- 真实 apply 必须带单主机或小批量 `--limit`。
130+
- 退出码 `1` 为失败,`2` 为参数错误,`10` 必须区分 RestartRequired 与外部 Blocked。
131+
- Windows OpenSSH 到 PSRP 切换失败时保留原 SSH 通道,不删除或改写 SSH 端口。
132+
- submodule 未初始化、dirty 或指针不在 GitHub 时,Ansible入口直接阻断。
133+
- secrets 仓库误公开、Forgejo/控制端疑似入侵或旧机器退役时,轮换所有相关凭据。
134+
135+
## 8. Rollback
136+
137+
- Submodule:revert 父仓库 `.gitmodules`、gitlink、同步脚本和 QA 排除 commit;子仓库不受影响。
138+
- Ansible:默认不 apply;已 apply 的 Windows PSRP bootstrap 可删除 Tailscale-IP listener、证书和对应防火墙规则,SSH 保持可用。
139+
- Provisioning:平台安装脚本继续拥有自身备份与恢复合同;Ansible 不另写不可逆安装逻辑。
140+
- Secrets:私有仓库只负责分发,不自动轮换;泄露时从被控系统重新签发凭据并提交替换值。
141+
142+
## 9. 未采用方案
143+
144+
- pyinfra:Windows 插件当前不适合生产级三平台管理。
145+
- 在 `powershellScripts` 复制 Ansible control plane:会产生重复 inventory、连接配置和角色边界。
146+
- Forgejo 作为 `powershellScripts` 主仓库并 push mirror GitHub:会引入 force mirror 语义并弱化 GitHub 公共协作边界。
147+
- GitHub/Forgejo 双 push:不能解决父仓库同时读取两个代码库的需求,且存在部分成功状态。
148+
- 使用 Forgejo mirror 作为 submodule URL:可能滞后,且把私人网络可达性带入公开依赖。
149+
- 把 secrets 仓库做成 submodule:会暴露私有 URL并让普通初始化流程尝试拉取明文凭据仓库。
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# 实施计划
2+
3+
## 0. 多仓库前置与任务边界
4+
5+
1. 当前任务作为跨仓库父规划,实施前分别在 `powershellScripts` 与 `self-hosted-compose` 创建/激活对应 Trellis 实施任务。
6+
2. `powershellScripts` 子任务拥有公共远程入口、平台脚本与测试。
7+
3. `self-hosted-compose` 子任务拥有 submodule、Ansible control plane、inventory 和文档。
8+
4. `powershellScripts-secrets` 只初始化仓库结构与说明,不与任一父仓库混合提交。
9+
5. 每个仓库分别执行 `git status`、验证和 Conventional Commit。
10+
11+
## 1. 固定 GitHub 权威版本
12+
13+
- [x] 确认 `powershellScripts` 当前计划纳入 submodule 的 commit 仅包含文档,无需运行 QA。
14+
- [x] 提交当前任务规划/公共代码变更,并推送到 GitHub `master`。
15+
- [x] 用 `git ls-remote` 验证 GitHub 包含目标 commit。
16+
- [x] 不依赖 Forgejo pull mirror 是否已同步。
17+
18+
风险点:当前本地 `master` 已领先 GitHub,不能在目标 commit 尚未推送时创建父仓库 gitlink。
19+
20+
## 2. 配置 self-hosted-compose submodule
21+
22+
- [x] 在 `self-hosted-compose` 创建独立 Trellis 实施任务并读取其 infra/backend specs。
23+
- [x] 确认父仓库工作树干净。
24+
- [x] 添加 GitHub submodule 到 `reference/powershellScripts`。
25+
- [x] 检查 `.gitmodules` 仅包含公开 GitHub URL和相对路径,不含本机绝对路径或私有 Forgejo URL。
26+
- [x] 在根 `package.json` 增加:
27+
- `submodules:status`
28+
- `submodules:update`
29+
- `submodules:pull`
30+
- [x] 在 `biome.json` 和 `.prettierignore` 排除整个 submodule 路径。
31+
- [x] 在 README/AGENTS 记录初始化、更新、dirty 状态、父子提交顺序和只读依赖边界。
32+
- [x] 不修改 `pnpm-workspace.yaml`,不复制完整 submodule-host 模板,不启用递归 push。
33+
34+
验证:
35+
36+
```bash
37+
git submodule status
38+
pnpm submodules:status
39+
pnpm submodules:update
40+
pnpm lint
41+
pnpm test
42+
pnpm check
43+
git diff --check
44+
```
45+
46+
额外验证:临时 fresh clone 或 deinit/init 后,`git submodule update --init --recursive` 能从 GitHub 获取固定 commit。
47+
48+
## 3. 初始化私有 secrets 仓库
49+
50+
- [ ] 通过 macmini Forgejo 用户命名空间创建 `powershellScripts-secrets`,明确验证仓库为 Private。
51+
- [ ] 本地 checkout 位于 `/Volumes/Data/projects/forgejo/powershellScripts-secrets`。
52+
- [ ] 增加中文 README、安全边界、恢复流程、凭据轮换触发条件和最小目录结构。
53+
- [ ] 不加入 SSH 私钥;只保存公钥/授权声明和用户确认允许的管理员密码、Token。
54+
- [ ] 禁用或不配置公开 mirror、公共 webhook 和不必要的 CI 日志输出。
55+
- [ ] 首次 commit/push 后用 Forgejo UI/API 和 `git remote -v` 验证私有远端与本地路径。
56+
57+
## 4. 扩展 Ansible control plane
58+
59+
- [ ] 锁定 Ansible collections 和 Python 依赖,确保 Linux/macOS/WSL2 一致。
60+
- [ ] 扩展 homelab inventory 的 Linux、darwin、windows 分组和 host vars。
61+
- [ ] 增加 secrets checkout 解析与缺失阻断,不提交绝对路径。
62+
- [ ] 增加 workstation bootstrap/provision/verify playbooks。
63+
- [ ] 默认 `provision_apply=false`,真实执行必须显式 `--limit` 和 apply 开关。
64+
- [ ] role 从 `reference/powershellScripts` 读取固定版本的入口与合同,不复制包清单。
65+
- [ ] 输出每台主机的阶段状态、退出码、重启要求和精确重跑命令。
66+
67+
验证:
68+
69+
```bash
70+
cd deployments/ansible
71+
ansible-galaxy collection install -r requirements.yml
72+
ansible-inventory --list --yaml
73+
ansible-playbook --syntax-check playbooks/workstation-bootstrap.yml
74+
ansible-playbook --syntax-check playbooks/workstation-provision.yml
75+
ansible-playbook --syntax-check playbooks/workstation-verify.yml
76+
```
77+
78+
## 5. Windows OpenSSH 到 PSRP bootstrap
79+
80+
- [ ] 在 `powershellScripts` 提供 Windows PowerShell 5.1 兼容、无 UAC 交互的固定 bootstrap 入口。
81+
- [ ] 发现并校验当前 Tailscale IPv4。
82+
- [ ] 创建/更新自签名证书和仅绑定该 IP 的 HTTPS listener `5986`。
83+
- [ ] 保持 `AllowUnencrypted=false`,使用 NTLM 和强制 message encryption。
84+
- [ ] 保留 Windows 防火墙全局状态;启用时添加 scoped rule,关闭时只验证监听地址。
85+
- [ ] 不修改现有 OpenSSH listener、端口、服务和授权配置。
86+
- [ ] Ansible 通过 SSH 执行 bootstrap 后,切换 PSRP 并运行 `win_ping`。
87+
- [ ] 绑定、证书或 PSRP 验证失败时仍可通过 SSH 回滚/重试。
88+
89+
测试与验证:
90+
91+
- Pester 覆盖 Tailscale IP 选择、listener 计划、证书重用、防火墙状态分支、幂等性和 rollback 计划。
92+
- `pnpm test:pwsh:all`。
93+
- `pnpm qa`。
94+
- Windows 实机先 DryRun/计划,再单机 bootstrap 和端口监听验证。
95+
96+
## 6. 三平台 Core 编排
97+
98+
- [ ] Linux/macOS 使用 SSH,Windows 正式阶段使用 PSRP。
99+
- [ ] 管理员机器阶段与普通用户 Stage 1 分离。
100+
- [ ] clone/更新公开 GitHub `powershellScripts`,版本来自父仓库 submodule gitlink。
101+
- [ ] 首期执行 `Core`;`Full` 仅显式 opt-in,不纳入完全无人值守验收。
102+
- [ ] 重启使用平台安全边界:Windows `win_reboot`,Linux/macOS 不擅自重启。
103+
- [ ] 调用平台 `99` 验证入口并解析 JSON。
104+
- [ ] 第二次运行验证幂等,仅处理缺失或 drift。
105+
106+
## 7. 最终质量门
107+
108+
- [ ] `powershellScripts`: `pnpm qa`。
109+
- [ ] 涉及 pwsh:`pnpm test:pwsh:all`。
110+
- [ ] `self-hosted-compose`: `pnpm check`。
111+
- [ ] 两个父/子仓库分别 `git status --short`。
112+
- [ ] `self-hosted-compose`: `git submodule status` 指向 GitHub 已存在 commit,submodule 工作树干净。
113+
- [ ] secrets 仓库:remote、private visibility、无 SSH 私钥、无意外生成物。
114+
- [ ] Ansible syntax/inventory 检查通过。
115+
- [ ] Linux/macOS/Windows 至少完成连接与 `Core` WhatIf;真实 apply 按用户确认的单机范围执行。
116+
117+
## 8. 提交顺序
118+
119+
1. `powershellScripts` 公共入口与测试 commit,推送 GitHub。
120+
2. `powershellScripts-secrets` 初始化 commit,推送私有 Forgejo。
121+
3. `self-hosted-compose` submodule gitlink、工程规范和 Ansible commit,推送私有 Forgejo。
122+
4. 若后续修改子仓库,始终先提交/推送子仓库,再更新父仓库 gitlink。

0 commit comments

Comments
 (0)