103 lines
4.0 KiB
Markdown
103 lines
4.0 KiB
Markdown
# 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,可一键在原站打开。
|
||
- 敏感配置留在本地 `config.json`,仓库只提交 `config.example.json`。
|
||
|
||
## 快速开始
|
||
|
||
```bash
|
||
cp config.example.json config.json
|
||
npm install
|
||
npm start
|
||
```
|
||
|
||
默认访问:<http://localhost:8788>
|
||
|
||
## 配置
|
||
|
||
编辑 `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` 中排除。
|
||
- 部分写操作接口(短信发送、网络模式、频段/小区锁定等)会改变设备状态,执行前请确认目标实例。
|