Files
nodeagent/docs/DEPLOY-LINUX.md
T
jkooe b9236dfaf1 chore(privacy): 公开仓库隐私脱敏 —— 清除可定位到个人与设备的字面量
按 security-reports/ 的隐私审查台账逐项收口。纯脱敏与表述泛化,
不含任何业务逻辑变更;实测结论与排查步骤一字未动。

P1(可定位到具体设备/个人)
- scripts/verify-b2.mjs:NA_URL 去掉硬编码缺省值(原指向一台真实机器),改为必填。
  这是全仓库唯一「拿着就能连到某台真机」的常量。
- 测试账户名 pdverify → na-test(docs/VM-VERIFICATION.md 7 处、docs/console-plan.md 1 处)
- 虚拟机与宿主的真实网段 → RFC 5737 文档保留段 192.0.2.x(含 CLOSE_WAIT 记录)
- 跨项目名与私人称呼 → 中性表述(docs/PRD.md、docs/DEVELOPMENT.md、docs/console-plan.md 等)

P2(低风险设备指纹)
- 虚拟化产品及其 CLI / 访客工具名 → 中性表述(12 个文件 + 1 个工作流注释)
- 测试目录 C:\nodeagent-test → C:\na-test
- NAS 设备型号与系统名 → NAS 设备 / NAS 系统(docs/DEPLOY-LINUX.md、scripts/install-linux.sh、README.md)
- 真机 CPU 型号、真机物理分辨率、代理软件品牌与监听端口、杀软品牌 → 泛化
- 单元测试示例段去掉真机 IP 尾八位:acl-v11 / net-scripts 的 fixture 与断言同步更新
- .gitignore 补 config.json / agent.json(含真实密钥与节点地址,绝不入库)
- 顺带移除混入技术文档的「不构成投资建议」字样(与文档主题无关)

验证:pnpm test:unit 340/340 通过;独立扫描器对 235 个跟踪文件做 17 类模式
全量扫描,命中 0。
2026-10-13 22:35:40 +08:00

138 lines
7.1 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.
# Linux 被控端部署(Debian 12 / Ubuntu / NAS 系统等 systemd 系统)
> 适用:把一台 Linux 机器作为**被控端**,让 Mac/Linux 控制端接管。
> 本文的能力清单是 **2026-10-13 在 Debian 12 容器里实测**得出的,不是推测。
---
## 0. 一句话
Linux 被控端 = **命令 / 状态 / 文件 / 审计**(服务器型用途);
**没有 GUI 能力**(截图、键鼠、窗口、剪贴板、音量均为 Windows/macOS 实现,
Linux 端未实现 —— 调用会明确返回 `E_UNSUPPORTED_PLATFORM`,不假装可用)。
---
## 1. 快速开始(以 NAS 设备为例)
```bash
# ① 把仓库放到 NAS 上(任选其一)
# - git clone https://github.com/jkooe/nodeagent.git
# - 或从控制端 scp 整个目录过去
# ② 生成被控端载荷(在**控制端**或任意有 Node 22+ 的机器上执行一次)
node scripts/pack.mjs # → release/agent.mjs
# ③ 在 NAS 上执行安装(需要 sudo;会自动注册 systemd 服务并开机自启)
cd nodeagent
sudo bash scripts/install-linux.sh --node-id nas-01
# ④ 抄下屏幕上打印的「密钥」与「连接命令」,回控制端执行:
# nodeagent connect <NAS的IP> --port 8765 --key <密钥> --insecure
```
**装完即自启**:`systemctl status nodeagent` 应为 `active (running)`;
重启 NAS 后也会自动拉起(`systemctl is-enabled nodeagent` → `enabled`)。
### 三种安装模式
| 模式 | 命令 | 程序目录 | 自启方式 | 适用 |
|---|---|---|---|---|
| **系统级**(默认) | `sudo bash scripts/install-linux.sh` | `/opt/nodeagent` | 系统 systemd(`multi-user.target`) | NAS / 服务器,需 sudo |
| **用户级** | `bash scripts/install-linux.sh --user` | `~/.local/share/nodeagent` | 用户 systemd + `linger` | 无 sudo 的场景 |
| **不注册服务** | `sudo bash scripts/install-linux.sh --no-service` | 同上(按模式定) | 自行安排(supervisor / cron `@reboot` / nohup) | systemd 受限的系统 |
其他参数:`--port 8765`、`--allow-input`(**Linux 上无实际输入能力**,仅留存配置)、
`--uninstall [--purge]`。
---
## 2. 运行依赖(脚本会自动处理能处理的)
| 依赖 | 是否必需 | 说明 |
|---|---|---|
| **Node ≥ 22** | 必需 | 脚本优先用系统 Node;**没有就自动下载** `node-v22.x-linux-<arch>` 到 `<安装目录>/runtime/`(用 npmmirror,国内快)。NAS 上通常没有 Node → 走自动下载 ✓ |
| **systemd** | 默认必需 | 用于开机自启。没有就加 `--no-service`(脚本会给出替代启动命令) |
| **bash** | 必需 | 安装脚本与部分能力用它。**Alpine 等只有 busybox 的系统需先装 bash**(`apk add bash`) |
| **procps(`ps`)** | **`system.process.list` 需要** | Debian/Ubuntu 自带 ✓;**精简容器镜像(如 `node:*-slim`)默认没有** → 表现为「进程列表为空」。装:`apt-get install -y procps` |
| **iproute2(`ip`)** | 可选 | 仅用于安装时显示本机 IP;缺失时脚本回退 `hostname -I` / `ifconfig`,再不行显示占位符 ✓ |
| **curl 或 wget** | 下载运行时时需要 | 若已装 Node 22+ 则不需要 |
> ⚠️ 实测踩到的坑:在 **Alpine** 容器里测会看到 `spawn /bin/bash ENOENT`,
> 极易误判成「Linux 不支持」——**实际是镜像没有 bash**。
> 同理 `node:22-slim` 里 `process.list` 返回空是**没有 procps**,不是代码问题。
---
## 3. Linux 上真实可用的能力(实测)
在同一台(Debian 12)机器上跑 `node scripts/verify.mjs` 的结果:
| 能力 | Linux | 说明 |
|---|---|---|
| `system.info` | ✅ | 返回 OS 名 "Linux"、CPU 核数、主机名 |
| `system.status` | ✅ | CPU / 内存 / 磁盘(多磁盘正常识别) |
| `system.process.list` | ✅** | 需 `procps`;缺则返回空列表 |
| `system.shell.exec` | ✅ | 含非零退出码回传、**超时强制终止**(实测 exit=124) |
| `system.service.list` | ⚠️ | Windows 服务概念,Linux 上退化为 systemd 单元(部分可用) |
| `system.audit.list` / 审计链 | ✅ | 与平台无关 |
| `system.task.*` | ✅ | 异步长任务框架 |
| `fs.*`(list/read/write/stat) | ✅ | 路径按 POSIX 语义(区分大小写) |
| `log.query` / `monitor.*` | ⚠️ 部分 | `monitor` 有 Windows 专属实现,部分子能力不可用 |
| `event.watch`(file/process/net) | ✅ | 与平台无关 |
| `system.agent.update`(自更新) | ✅ | 与平台无关 |
| `screen.*` / `input.*` / `window.*` / `clipboard.*` / `audio.*` / `record.*` | ❌ | **未实现** → 明确返回 `E_UNSUPPORTED_PLATFORM` |
| `app.list` / `app.install` | ❌ | winget 专属 → 同样明确拒绝 |
**汇总对比**:本机 macOS 15 通过/0 失败;Linux(Debian 12)**9 通过 / 1 失败(缺 procps)/ 6 跳过**(跳过的都是 GUI 类)。
---
## 4. 管理命令
```bash
# 系统级
systemctl status nodeagent
journalctl -u nodeagent -f # 实时日志
systemctl restart nodeagent
sudo bash scripts/install-linux.sh --uninstall # 卸载(保留配置与审计日志)
sudo bash scripts/install-linux.sh --uninstall --purge # 连数据目录一起删
# 用户级:把上面命令里的 systemctl / journalctl 加 --user
```
**配置与数据**(`~/.nodeagent`,与 agent 侧 `agentDir()` 一致):
| 文件 | 内容 |
|---|---|
| `agent.json` | 节点 ID / 端口 / **密钥**(权限 600)/ 认证模式 |
| `audit.log` | 审计日志(JSONL,10MB 轮转留 5 份) |
| `audit-anchors.jsonl` | 审计链锚点(启用锚定后产生) |
---
## 5. 故障排查(按实测顺序)
| 现象 | 原因 | 处理 |
|---|---|---|
| `未检测到 systemd` | 容器/非 systemd 系统 | 加 `--no-service`,或改用 supervisor |
| `spawn /bin/bash ENOENT` | **系统没有 bash**(Alpine 等) | `apk add bash` / `apt-get install -y bash` |
| `进程列表为空` | **没有 `ps`**(slim 镜像) | `apt-get install -y procps` |
| 脚本"跑到一半就没了" | `set -e` 下某个命令替换失败(如缺 `ip`) | 已在 v2.0.3+ 加固为多级回退;旧版请升级脚本 |
| 控制端连不上,被控端却显示已监听 | 防火墙 | Debian: `ufw allow 8765/tcp`;firewalld: `firewall-cmd --add-port=8765/tcp --permanent && firewall-cmd --reload` |
| `E_AUTH_FAILED` | 密钥不一致 | 以被控端 `~/.nodeagent/agent.json` 的 `key` 为准 |
| GUI 能力报 `E_UNSUPPORTED_PLATFORM` | **正常**(Linux 无 GUI 实现) | 无需处理;这是「诚实拒绝」而非故障 |
---
## 6. 建议(服务器型被控端)
1. **尽快启用审计链外部锚定** —— 把链头存到 NAS 之外(云盘/另一台机器)。
本机锚点等于没锚:被控端被 root 后锚点也会一起被改。
```bash
node scripts/anchor-audit.mjs collect --out /tmp/anchor-$(date +%Y%m%d).jsonl
# 再把该文件上传到云盘,之后用 verify 子命令比对
```
2. **不要开 `--allow-input`** —— Linux 上无实际输入能力,开着只是加大配置面。
3. 若机器只有公网无内网互通,考虑用 **Hub 中转**(被控端主动外连,穿 NAT)。