Skip to content

Commit e94abae

Browse files
committed
docs(task): 记录 Ansible 主机准备方案
1 parent 15345e3 commit e94abae

8 files changed

Lines changed: 485 additions & 1 deletion

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: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# 三平台 Ansible 被控端准备设计
2+
3+
## 1. 边界与目录
4+
5+
三个本机入口拥有平台检测和最小系统变更,现有 Stage 0/Stage 1 与 Ansible control plane 保持不变:
6+
7+
```text
8+
linux/bootstrap/prepare-ansible-host.sh
9+
macos/bootstrap/prepare-ansible-host.zsh
10+
windows/bootstrap/Prepare-WindowsAnsibleHost.ps1
11+
```
12+
13+
准备完成后的调用链为:
14+
15+
```text
16+
本机准备脚本 -> SSH 首次连接 -> Windows PSRP bootstrap(仅 Windows)
17+
-> Ansible Stage 0/Stage 1 -> 99 结构化验证
18+
```
19+
20+
## 2. 公共接口
21+
22+
Unix 参数:
23+
24+
```text
25+
--apply
26+
--output-format text|json
27+
--ssh-port <1..65535>
28+
```
29+
30+
Windows 参数:
31+
32+
```powershell
33+
[-Apply] [-OutputFormat Text|Json] [-SshPort <1..65535>]
34+
[-TailscaleIPv4 <100.64.0.0/10 address>]
35+
```
36+
37+
默认 Operation 为 `Preview`,显式 apply 为 `Apply`。结果项使用 `Name`、`Status`、`ExitCode`、`Message`、`Changed`;顶层按 `Failed/1 > Blocked/10 > Succeeded/0` 聚合。
38+
39+
JSON stdout 只承载结果 document;进度和诊断写 stderr,避免控制端解析污染。
40+
41+
## 3. 预检与写入顺序
42+
43+
所有平台先执行零副作用预检:
44+
45+
1. 参数和平台。
46+
2. apply 权限。
47+
3. Tailscale CLI、daemon 和唯一 CGNAT IPv4。
48+
4. 当前 SSH/Python/service 状态。
49+
5. 生成完整 action plan。
50+
51+
脚本可以为缺失项生成并执行安装计划。若安装完成后仍需要 tailnet 登录、系统授权、重启或重新登录,则保留已完成安装,返回 Blocked 并输出全部人工步骤。
52+
53+
## 4. Linux adapter
54+
55+
- 从 `/etc/os-release` 解析 Debian/Ubuntu 或 Arch family。
56+
- Debian 使用 `apt-get update` 与 `apt-get install -y openssh-server python3 sudo curl ca-certificates`,Tailscale 复用官方 `https://tailscale.com/install.sh`。
57+
- Arch 使用 `pacman -Syu --needed --noconfirm openssh python sudo curl ca-certificates`,Tailscale 复用官方安装脚本支持的仓库配置,避免部分升级。
58+
- 通过 `systemctl enable --now ssh|sshd` 管理服务;服务名按已存在 unit 和发行版 family 选择。
59+
- Tailscale 安装后启用 `tailscaled`;未登录时输出 `sudo tailscale up`、浏览器授权和 `tailscale ip -4` 验证步骤。
60+
- `sudo -n true` 是非交互接管能力的硬检查。脚本由 root 执行时视为满足。
61+
- WSL 不自动创建独立 SSH 管理面,返回 Blocked。
62+
63+
## 5. macOS adapter
64+
65+
- Remote Login 状态由 `/usr/sbin/systemsetup -getremotelogin` 读取,apply 使用 `sudo /usr/sbin/systemsetup -setremotelogin on`。
66+
- Python 优先选择 `/usr/bin/python3`,其次选择 PATH 中的 `python3`。
67+
- Python 缺失且 `brew` 已存在时执行 `brew install python`;Homebrew 缺失时复用 `macos/01installHomebrew.zsh`。
68+
- Tailscale 缺失时使用 `brew install --cask tailscale`,随后打开 `/Applications/Tailscale.app`;系统扩展批准与账号登录作为 ManualSteps。
69+
- `systemsetup` 权限拒绝映射为 Blocked,不把 Full Disk Access 问题误报成普通执行失败。
70+
71+
## 6. Windows adapter
72+
73+
- 使用 `Get-WindowsCapability -Online -Name OpenSSH.Server*` 判断 capability;只接受系统 capability,不下载 Win32-OpenSSH。
74+
- 安装后重新读取 `sshd`,设置 `StartupType=Automatic` 并启动。
75+
- DefaultShell 固定为 Windows PowerShell 5.1,确保首次 Ansible SSH 路径与官方支持合同一致。
76+
- Tailscale 缺失时使用 winget 安装;安装器需要重启或 GUI 登录时输出对应 ManualSteps。
77+
- 只读取防火墙 profile/rule 和 TCP listener,不创建、删除或启用 rule,也不覆盖 `sshd_config`。
78+
- Windows 无 Python 要求,`PythonPath` 输出为 null;正式 PSRP 管理由既有 bootstrap 接管。
79+
80+
## 7. Tailscale 发现
81+
82+
- 显式 IP 优先;否则调用 Tailscale CLI 获取 IPv4。
83+
- 只接受唯一 `100.64.0.0/10` IPv4,拒绝 LAN、loopback、IPv6、多地址歧义。
84+
- Linux/macOS 从 PATH 查找 `tailscale`;macOS另检查 App bundle CLI 路径;Windows 同时检查 PATH 和标准安装路径。
85+
- Linux 可执行交互式 `tailscale up`;macOS/Windows 默认引导 GUI 登录。脚本不接受或持久化 auth key。
86+
- `ManualSteps` 每项包含 `Name`、`Location`、`Command`、`VerifyCommand` 和 `Reason`,Text/Json 使用同一数据源。
87+
88+
## 8. 复用策略
89+
90+
- 复用既有 Windows bootstrap 的管理员判断与 Tailscale IPv4 校验思想,但不让新入口依赖 Stage 0 模块的包清单。
91+
- 不直接调用旧 `Enable-WindowsOpenSsh.ps1`,因为该脚本还拥有防火墙和 `sshd_config` 变更,超过本任务安全边界。
92+
- Unix 两个平台共享 JSON schema 和状态词,但保留独立 shell 实现,避免为三个短入口增加新的跨语言 runtime。
93+
94+
## 9. Rollback
95+
96+
- Preview 无副作用。
97+
- SSH/Python package 安装不提供自动卸载,避免删除用户已有依赖。
98+
- 服务启用可由用户按输出命令手工关闭;脚本不自动回滚已成功的基础能力。
99+
- Windows DefaultShell 可删除注册表值恢复 `cmd.exe`,但不会作为失败时自动 rollback,以免改变已建立的 SSH 会话假设。
100+
- 任何失败都在 Results 中保留已完成步骤,便于人工决定恢复或重跑。
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: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# 实施计划
2+
3+
## 1. 公共合同与测试夹具
4+
5+
- [x] 固定三平台 schema、状态、退出码和 Text/Json 输出字段。
6+
- [x] 增加 fixture 环境变量或可注入命令路径,使 Linux/macOS 计划测试不执行真实 sudo、包管理器、service 或 Tailscale。
7+
- [x] 增加 Windows 纯计划函数和可注入状态,使 Pester 可测试 Preview 与计划函数。
8+
9+
## 2. Linux 入口
10+
11+
- [x] 新增 `linux/bootstrap/prepare-ansible-host.sh`。
12+
- [x] 实现参数、发行版、WSL、sudo、Tailscale、Python、SSH package/service 检查。
13+
- [x] 实现 Debian/Ubuntu 和 Arch apply adapter,自动安装 Tailscale/SSH/Python/sudo 并保证 package/service 幂等。
14+
- [x] 实现 Text/Json 单文档输出和精确重跑命令。
15+
16+
## 3. macOS 入口
17+
18+
- [x] 新增 `macos/bootstrap/prepare-ansible-host.zsh`。
19+
- [x] 实现 sudo、Tailscale、Remote Login、Python/Homebrew 检查。
20+
- [x] apply 时启用 Remote Login;复用现有 Stage 0 自动补 Homebrew,再安装 Python 和 Tailscale。
21+
- [x] 将 Full Disk Access 等权限拒绝映射为 Blocked/10。
22+
23+
## 4. Windows 入口
24+
25+
- [x] 新增 Windows PowerShell 5.1 兼容的 `windows/bootstrap/Prepare-WindowsAnsibleHost.ps1`。
26+
- [x] 实现管理员和 Administrators 组、Tailscale、capability、service、listener、DefaultShell、防火墙状态检查。
27+
- [x] apply 时通过 winget 自动补 Tailscale,并安装 Microsoft OpenSSH Server、设置 Automatic/Running 和 Windows PowerShell 5.1 DefaultShell。
28+
- [x] 输出 `iminipro820` 的 SSH 验证命令与下一阶段 PSRP bootstrap 命令。
29+
- [x] 确保文件为 UTF-8 BOM,不触碰 `sshd_config` 和防火墙全局状态。
30+
31+
## 5. 自动化测试
32+
33+
- [x] Pester 覆盖结果聚合、唯一 Tailscale IPv4、Windows capability/service/DefaultShell 计划、非管理员 apply 和 JSON 单文档。
34+
- [x] shell 测试覆盖 Linux 发行版 adapter、WSL Blocked、macOS Remote Login/Python 分支和默认 Preview 零写入。
35+
- [x] 执行 `bash -n linux/bootstrap/prepare-ansible-host.sh`。
36+
- [x] 执行 `zsh -n macos/bootstrap/prepare-ansible-host.zsh`。
37+
- [x] 执行 PowerShell parser 与 UTF-8 BOM 断言。
38+
39+
## 6. 文档与实机命令
40+
41+
- [x] 更新远程装机 research/使用文档,记录三平台本机准备命令。
42+
- [x] 为 `iminipro820` 给出管理员 PowerShell Preview、Apply、服务验证和控制端 SSH 命令。
43+
- [x] 明确 TCP 22 默认可能监听 LAN 与 Tailscale,准备脚本不声明 Tailscale-only。
44+
45+
## 7. 质量门
46+
47+
- [x] 运行目标窄测。
48+
- [x] 运行 `pnpm qa`。
49+
- [x] 运行 `pnpm test:pwsh:all`。
50+
- [x] 运行 `git diff --check` 和 `git status --short`。
51+
- [ ] 用户在 `iminipro820` 上完成 Preview;真实 apply 和跨机 SSH 作为实机验收,不在 macOS 控制端伪造。
52+
53+
## 风险与恢复点
54+
55+
- macOS `systemsetup` 可能受 Full Disk Access 限制,必须保留 Blocked 提示,不能反复重试或绕过系统策略。
56+
- Windows capability 安装依赖 Windows Update/Features on Demand;失败时保留原系统状态并输出 DISM/capability 诊断。
57+
- 不调用旧 OpenSSH 加固入口,避免覆盖认证配置后失去首次连接通道。
58+
- 不自动使用 Tailscale auth key;需要账号授权时通过 ManualSteps 引导交互登录,避免把 auth key 引入公开仓库或命令历史。
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# 三平台 Ansible 被控端准备脚本
2+
3+
## Goal
4+
5+
提供可在目标机本地执行的三平台准备入口,把 Linux、macOS、Windows 主机准备到可由 `self-hosted-compose` 中 Ansible control plane 首次接管的状态,并输出可供人工或后续自动化解析的检查结果。
6+
7+
## Background
8+
9+
- 控制端可能是 Linux、macOS、Windows WSL2,或通过 VS Code Remote SSH 登录的 Linux;本任务不在控制端安装 Ansible,也不增加定时运行。
10+
- Linux/macOS 正式连接使用 SSH;Windows 首次连接使用 Microsoft OpenSSH,后续由既有 `Enable-WindowsRemotePsRemoting.ps1` 切换到 PSRP HTTPS。
11+
- Windows 目标机 `iminipro820` 已接入 Tailscale,地址为 `100.125.34.90`,用户为 `mudssky`,当前没有 `sshd`。
12+
- 官方 Ansible 文档要求 Unix managed node 具备受支持的 Python;Windows SSH 应使用系统 capability 提供的 Microsoft OpenSSH,并推荐将 `DefaultShell` 设为 Windows PowerShell 5.1。
13+
- 仓库已有 OpenSSH 加固模板和人工启用脚本,但准备阶段不能在尚未配置公钥时覆盖认证配置或关闭密码登录。
14+
15+
## Requirements
16+
17+
### R1 统一调用与结果合同
18+
19+
- 新增以下入口:
20+
- `linux/bootstrap/prepare-ansible-host.sh`
21+
- `macos/bootstrap/prepare-ansible-host.zsh`
22+
- `windows/bootstrap/Prepare-WindowsAnsibleHost.ps1`
23+
- 三个平台默认只生成 Preview,不修改系统;真实变更必须显式使用 `--apply` 或 `-Apply`。
24+
- 支持 Text 和 Json 输出;JSON stdout 必须只有一个 document。
25+
- 统一输出至少包含 `SchemaVersion`、`Platform`、`Operation`、`Status`、`ExitCode`、`HostName`、`UserName`、`TailscaleIPv4`、`SshPort`、`PythonPath`、`Results` 和 `RerunCommand`。
26+
- 退出码固定为:`0` 成功、已满足或 Preview;`1` 执行/验证失败;`2` 参数或平台输入错误;`10` 外部权限、交互登录或人工操作导致的 Blocked。
27+
- 重复 apply 必须幂等,已满足的 capability、package、service 和配置不得重复修改。
28+
29+
### R2 公共安全边界
30+
31+
- 准备入口只负责建立 Ansible 首次连接所需的本机前置,不执行 Stage 0/Stage 1 软件安装,不运行 Ansible playbook。
32+
- Tailscale 做安装状态、运行状态和唯一 `100.64.0.0/10` IPv4 检查;缺失时由脚本使用各平台官方安装路径自动安装。
33+
- 无法可靠无交互完成的登录、GUI/系统权限授权、重启或重新登录必须返回 `Blocked/10`,并在 `ManualSteps` 中给出操作位置、完整命令、验证命令和重跑命令。
34+
- 不自动使用 Tailscale auth key;安装后未登录时引导用户执行交互式 `tailscale up` 或平台 GUI 登录。
35+
- 不修改任何平台防火墙的全局启用/关闭状态。
36+
- 不写入 SSH 私钥,不自动生成或分发控制端私钥。
37+
- 不覆盖现有 `sshd_config`、`authorized_keys` 或认证策略;SSH 加固和公钥分发由后续 Ansible role 处理。
38+
- 所有真实系统变更前先完成参数、平台、权限和 Tailscale 地址预检,避免部分写入。
39+
40+
### R3 Linux 准备
41+
42+
- 支持仓库既有范围内的 Ubuntu/Debian 与 Arch Linux;其他发行版返回 `Blocked/10`。
43+
- 检查当前用户、非交互 sudo、唯一 Tailscale IPv4、SSH 端口、Python 3 和 systemd/OpenRC 可用性。
44+
- apply 时按发行版安装缺失的 `openssh-server`、`python3`、`sudo` 和 Tailscale,启用并启动 `ssh`/`sshd` 与 `tailscaled` 服务。
45+
- WSL 客体不作为独立 SSH 被控端自动启用服务;检测到 WSL 时返回 `Blocked/10`,提示从宿主或显式设计的 WSL 通道管理。
46+
47+
### R4 macOS 准备
48+
49+
- 检查当前用户、sudo、唯一 Tailscale IPv4、Remote Login 状态和 Python 3。
50+
- apply 时使用系统 `systemsetup` 启用 Remote Login,不修改 macOS Application Firewall。
51+
- Python 3 已存在时直接复用;缺失时通过 Homebrew 安装 `python`。
52+
- Homebrew 缺失时,apply 复用仓库既有 `macos/01installHomebrew.zsh` 安装,再安装 `python` 和 Tailscale cask;需要用户确认 sudo 时允许终端交互。
53+
- Tailscale 安装后需要 GUI/System Extension/登录确认时返回 `Blocked/10`,列出打开 App、批准系统扩展、登录和验证地址的完整步骤。
54+
- 若 `systemsetup` 因 Full Disk Access 或其他 macOS 权限策略拒绝执行,返回 `Blocked/10` 并给出可操作提示。
55+
56+
### R5 Windows 准备
57+
58+
- 入口兼容 Windows PowerShell 5.1,含中文字符串的 `.ps1` 使用 UTF-8 BOM。
59+
- Preview 可在非管理员进程中生成;apply 必须在管理员 PowerShell 中执行,不请求 UAC。
60+
- 检查 `mudssky` 当前身份及本地 Administrators 组成员关系、唯一 Tailscale IPv4、`OpenSSH.Server~~~~0.0.1.0` capability、`sshd` 服务、TCP 22 和 DefaultShell。
61+
- apply 时安装缺失的 Microsoft OpenSSH Server capability,将 `sshd` 设置为 Automatic 并启动,把 `HKLM:\SOFTWARE\OpenSSH\DefaultShell` 设置为 `C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe`。
62+
- Tailscale 缺失时优先使用 `winget install --id Tailscale.Tailscale --exact`;winget 不可用时返回 `Blocked/10`,给出官方下载安装和 GUI 登录步骤。
63+
- 不调用现有 OpenSSH 加固脚本的防火墙或 `sshd_config` 覆盖路径;不改变已有端口、listener 和认证配置。
64+
- 防火墙开启时只报告现有 OpenSSH rule 是否可能放行;防火墙关闭时保持关闭。脚本不得声称 TCP 22 只监听 Tailscale,因为 Windows OpenSSH 默认可能监听所有接口。
65+
- 成功结果给出 `ssh mudssky@100.125.34.90` 和后续 PSRP bootstrap 的建议命令。
66+
67+
### R6 验证与文档
68+
69+
- 为三平台结果聚合、参数校验、Preview 零写入、平台计划和关键 Blocked 分支增加自动化测试。
70+
- shell 入口通过 `bash -n` / `zsh -n`;Windows 入口通过 PowerShell parser 和 UTF-8 BOM 检查。
71+
- 文档说明三平台本地执行命令、Windows `iminipro820` 首次操作、apply 后从控制端验证 SSH 的步骤。
72+
73+
## Acceptance Criteria
74+
75+
- [x] 三个平台都有默认 Preview、显式 apply 的准备入口,并遵守统一 JSON/退出码合同。
76+
- [x] Linux 能为 Ubuntu/Debian 与 Arch 生成正确 package/service 计划,WSL 和未知发行版明确 Blocked。
77+
- [x] macOS 能检查/启用 Remote Login,并正确处理 Python、Homebrew和 Full Disk Access 分支。
78+
- [x] Windows 能检测并安装 Microsoft OpenSSH Server、启动和自启 `sshd`、设置 PowerShell 5.1 DefaultShell。
79+
- [x] 所有平台验证唯一 Tailscale IPv4;缺失时自动安装 Tailscale,无法自动登录时给出完整人工步骤。
80+
- [x] 结构化结果包含 `ManualSteps`,每个外部 Blocked 都能按步骤操作并得到精确重跑命令。
81+
- [x] 准备流程不修改防火墙全局状态、SSH 认证配置、私钥或现有 `sshd_config`。
82+
- [ ] JSON stdout 可直接解析为一个 document,第二次 apply 不产生无意义变更。
83+
- [x] `pnpm qa`、`pnpm test:pwsh:all`、shell parser 和 `git diff --check` 通过。
84+
- [ ] 在 `iminipro820` 上先 Preview、再管理员 apply,最后从控制端成功执行 `ssh mudssky@100.125.34.90`。
85+
86+
## Out of Scope
87+
88+
- 安装操作系统、PXE、WinPE、Autounattend、云主机创建。
89+
- 在被控端安装或运行 Ansible、配置定时任务或常驻 agent。
90+
- 自动使用 Tailscale auth key、自动批准设备或管理 tailnet ACL。
91+
- SSH 公私钥生成、私钥同步、凭据仓库写入和密码轮换。
92+
- 覆盖 `sshd_config`、关闭密码登录或完成最终 SSH 加固。
93+
- Windows PSRP listener 创建;继续由既有远程 PSRP bootstrap 负责。

0 commit comments

Comments
 (0)