Files
multi-simadmin/README.md
T
chick 5016586922 test: give process-spawning suites room and pin the fused behaviour
The runtime executables bind fixed ports, so the production command check now
skips instead of failing against a live deployment, and the canary check takes
a reserved free port. Raise the default test timeout for the SQLite and browser
suites that were only slow under full-suite parallelism.
2026-09-05 18:53:05 +08:00

164 lines
8.3 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.
# Multi SimAdmin
一个用于聚合管理多个 [SimAdmin](https://github.com/3899/SimAdmin) 实例的轻量本地运维面板。
## 功能
- 只需要在 `config.json` 配置多个 SimAdmin 地址。
- Animal Island / 动森风格 Dashboard:暖米色背景、棕色文字、Ribbon 飘带标题、NookPhone 应用格、胶囊按钮与波点卡片。
- UI 内直接新增、编辑、删除设备地址,配置实时写入本地 `config.json`,并提供返回首页入口。
- 实例舰队列表、状态筛选、搜索、当前设备摘要。
- 支持无密码实例状态读取;有密码实例可通过本地服务代登录并保持会话。
- 统一代理 SimAdmin API,内置 API 工作台,便于读取/调试设备、SIM、网络、短信、eSIM、OTA 等接口。
- 保留原始 SimAdmin 页面 iframe 嵌入;若目标站禁止 iframe,可一键在原站打开。
- 融合 [SimAdminHub](https://github.com/3899/SimAdminHub) 的管理思路:跨节点短信、通知、自动化与跨域健康自然融入 Fleet 节点总览体系,无需部署或接入外部 Hub。
- 敏感配置留在本地 `config.json`,仓库只提交 `config.example.json`
## 一键安装(macOS
```bash
curl -fsSL https://gitea.chickliu.fun/Hermes/multi-simadmin/raw/branch/main/scripts/install.sh | sh
```
脚本会从 Gitea 下载源码,固定使用 pnpm `11.13.0` 安装依赖并构建 Web,然后启动:
- LAN Gateway`0.0.0.0:8788`
- Control-plane API`127.0.0.1:8790`
- Canary Gateway`8789` 保持关闭
安装完成后按终端输出访问 `http://<本机局域网 IP>:8788/fleet`。首次密码可在当前管理台直接设置。Gateway 默认监听所有网络接口,因此必须确保主机仅接入可信内网或已通过防火墙限制 8788 的来源;HTTP 部署不得直接暴露到公网,公网开放必须由前置代理提供 HTTPS 和访问控制。
> 当前生产秘密存储使用 macOS Keychain,因此一键安装脚本暂只支持 macOS。脚本不会覆盖已有源码目录或数据库,也不会占用已被其他进程监听的 8788/8790 端口。
### 服务管理
下载脚本后可执行完整生命周期命令:
```bash
curl -fsSL https://gitea.chickliu.fun/Hermes/multi-simadmin/raw/branch/main/scripts/install.sh -o /tmp/multi-simadmin-install.sh
sh /tmp/multi-simadmin-install.sh status
sh /tmp/multi-simadmin-install.sh restart
sh /tmp/multi-simadmin-install.sh stop
sh /tmp/multi-simadmin-install.sh start
sh /tmp/multi-simadmin-install.sh uninstall
```
`uninstall` 默认只移除程序源码,保留数据库、Gateway token 和日志。默认安装位置为 `~/Library/Application Support/multi-simadmin`,可通过 `MULTI_SIMADMIN_HOME` 覆盖;额外 LAN Host 可通过 `MULTI_SIMADMIN_ALLOWED_HOSTS`(逗号分隔)配置。
### Fleet 节点总览与跨域健康
`/fleet` 读取本机 Control Plane 中的节点状态、资源快照与设备号码,形成节点总览。侧栏在实例总数 / 在线 / 需处理之外,还聚合跨域健康指标:
- 短信异常:标记哪些节点的短信接口不可用,点击直达 `/fleet/messages`
- 通知异常:汇总跨节点通知队列的 pending + failed 数量,点击直达 `/fleet/notifications`
节点卡片直接进入对应实例详情,查看 CPU、内存、温度、SIM 号码、平台与版本。
### 跨节点短信中心
`/fleet/messages` 融合官方 SimAdminHub 的短信中心形态:它通过本地 Control Plane 按节点读取 SimAdmin 的 `/api/sms/list`,再跨设备聚合搜索、展示与发送。
- 跨设备记录:汇总各节点最新短信,支持按号码、内容或节点名称搜索,并分页加载。
- 会话视图:按号码分组为会话,节点栏 / 会话栏 / 消息栏三栏工作流,默认打开最新会话。
- 发送短信:从可用节点下拉选择目标设备,提交到 `/api/v1/fleet/messages/send` 后由 Control Plane 转发到对应 SimAdmin。
- 批量删除:可在短信记录中勾选选择并确认删除,Control Plane 通过严格白名单的 `/api/sms/batch-delete` 按节点批量清理,未成功项会以逐条失败原因返回。
- 安全边界:短信正文与号码只在本地页面展示;批量删除请求最多 500 条,且不接收外部 Hub 地址、Webhook 或任何可注入字段。
### 跨节点通知中心
`/fleet/notifications` 融合官方 SimAdminHub 的通知中心能力:它按本地节点聚合阅读 SimAdmin 的通知接口,再跨设备汇总转发通道、转发规则、转发日志与失败重试队列。
- 设备可用性:自动登录后读取 `/api/notifications/config``/api/notifications/logs``/api/notifications/queue`,无法读取的实例单独标记。
- 转发通道:统计通道总数、启用数以及常见的 webhook、Bark、PushPlus、企业微信、钉钉、飞书、Telegram、邮件等类型。
- 转发日志:展示成功、失败、免打扰、未匹配、无可用通道与最近记录。
- 失败重试:展示待发送、定时、重试中、发送中和失败的队列摘要,并支持整队列重试、单条重试或删除积压项。
- 安全边界:只返回经过白名单清洗的计数与最近条目,不暴露通知原文、webhook/token/secret 或模板配置。
## 旧版开发入口
`server/``public/` 仅用于历史兼容和开发验证,不是当前生产安装入口:
```bash
cp config.example.json config.json
npm install
npm start
```
## 配置
编辑 `config.json`
```json
{
"server": { "host": "127.0.0.1", "port": 8788 },
"instances": [
{
"id": "simadmin-open",
"name": "无密码 SimAdmin",
"url": "http://192.168.68.1:3000",
"description": "密码保护关闭或尚未配置密码的实例",
"auth": { "mode": "none" },
"tags": ["open"]
},
{
"id": "simadmin-password",
"name": "有密码 SimAdmin",
"url": "http://192.168.68.2:3000",
"description": "服务端代登录并保存会话 Cookie;密码只保存在本地 config.json",
"auth": {
"mode": "password",
"password": "CHANGE_ME"
},
"tags": ["password"]
}
]
}
```
字段说明:
- `id`:唯一标识,只能包含字母、数字、下划线、短横线、点号。
- `name`:页面显示名称。
- `url`SimAdmin 原始访问地址。
- `description`:可选描述。
- `auth.mode``none` 表示无密码;`password` 表示由本地聚合服务代登录。
- `auth.password`:可选。本地保存后可自动刷新会话;不要提交真实密码。
### 为什么只接受 IP 地址?
聚合服务会代理设备管理 API。为避免 DNS 重绑定将已校验主机名切换到本机或元数据地址,设备 URL 必须使用明确的 IPv4/IPv6 字面地址;局域网 IP(如 `192.168.x.x`)可正常使用。
## 常用命令
```bash
npm test
npm start
```
## 架构与阶段边界
第一阶段采用无构建链的可组合架构:
- `server/index.js` 是唯一 bootstrap,负责路径、监听和优雅关闭;`server/app.js``buildApp()` 无导入副作用,可通过 Fastify `inject()` 测试。
- `server/config/` 提供 immutable snapshot、串行事务和 temp + atomic rename;模板只用于首次加载,提交始终写实际 `config.json`
- `server/clients/` 在配置成功提交后 reconcile;`server/status/``server/proxy/` 是独立边界。
- `public/domain``infrastructure``state``router` 放置 Node 可测试模块,`app.js` 暂作 DOM composition/controller。
- `styles.css` 依次导入 tokens、base、components、responsive。
验证命令:
```bash
npm test
find server public test -name '*.js' -exec node --check {} \;
npm audit --omit=dev --audit-level=high
git diff --check
```
第二阶段安全加固后,服务仅允许监听 loopback;显式配置 `0.0.0.0`、LAN 地址或非 loopback 主机将拒绝启动。实例目标必须为允许的 IP 字面地址,拒绝凭据、loopback、unspecified、link-local、metadata、multicast 及主机名,以避免 DNS 重绑定。生产代理使用精确路径/方法白名单,写操作要求短期一次性确认令牌。
## 注意
- 当前项目是本地管理面板,不修改 SimAdmin 本体。
- `config.json` 可能包含真实设备地址和密码,已在 `.gitignore` 中排除。
- 部分写操作接口(短信发送、网络模式、频段/小区锁定等)会改变设备状态,执行前请确认目标实例。