feat(installer): support Linux hosts with XDG data root and ss port probe

- platform gate accepts Darwin and Linux; other platforms are refused
- default install root follows each platform's convention
  (~/Library/Application Support vs ~/.local/share)
- LAN IP discovery uses ip -4/hostname -I on Linux, ipconfig on macOS
- port occupancy checks fall back from lsof to ss
- API process gets MULTI_SIMADMIN_SECRET_BACKEND pinned per platform
- README documents the per-platform secret storage
This commit is contained in:
chick
2026-09-07 01:36:04 +08:00
parent e4c4bce75b
commit 3c5971e167
2 changed files with 39 additions and 14 deletions
+3 -3
View File
@@ -14,7 +14,7 @@
- 融合 [SimAdminHub](https://github.com/3899/SimAdminHub) 的管理思路:跨节点短信、通知、自动化与跨域健康自然融入 Fleet 节点总览体系,无需部署或接入外部 Hub。 - 融合 [SimAdminHub](https://github.com/3899/SimAdminHub) 的管理思路:跨节点短信、通知、自动化与跨域健康自然融入 Fleet 节点总览体系,无需部署或接入外部 Hub。
- 敏感配置留在本地 `config.json`,仓库只提交 `config.example.json` - 敏感配置留在本地 `config.json`,仓库只提交 `config.example.json`
## 一键安装(macOS ## 一键安装(macOS / Linux
```bash ```bash
curl -fsSL https://gitea.chickliu.fun/Hermes/multi-simadmin/raw/branch/main/scripts/install.sh | sh curl -fsSL https://gitea.chickliu.fun/Hermes/multi-simadmin/raw/branch/main/scripts/install.sh | sh
@@ -28,7 +28,7 @@ curl -fsSL https://gitea.chickliu.fun/Hermes/multi-simadmin/raw/branch/main/scri
安装完成后按终端输出访问 `http://<本机局域网 IP>:8788/fleet`。首次密码可在当前管理台直接设置。Gateway 默认监听所有网络接口,因此必须确保主机仅接入可信内网或已通过防火墙限制 8788 的来源;HTTP 部署不得直接暴露到公网,公网开放必须由前置代理提供 HTTPS 和访问控制。 安装完成后按终端输出访问 `http://<本机局域网 IP>:8788/fleet`。首次密码可在当前管理台直接设置。Gateway 默认监听所有网络接口,因此必须确保主机仅接入可信内网或已通过防火墙限制 8788 的来源;HTTP 部署不得直接暴露到公网,公网开放必须由前置代理提供 HTTPS 和访问控制。
> 当前生产秘密存储使用 macOS Keychain因此一键安装脚本暂只支持 macOS。脚本不会覆盖已有源码目录或数据库,也不会占用已被其他进程监听的 8788/8790 端口。 > 秘密存储按平台自动选择:macOS 使用 KeychainLinux 使用数据目录下 0600 权限的 `secrets.json` 文件;也可用 `MULTI_SIMADMIN_SECRET_BACKEND=macos-keychain|secret-file` 显式指定。脚本不会覆盖已有源码目录或数据库,也不会占用已被其他进程监听的 8788/8790 端口。
### 服务管理 ### 服务管理
@@ -43,7 +43,7 @@ sh /tmp/multi-simadmin-install.sh start
sh /tmp/multi-simadmin-install.sh uninstall sh /tmp/multi-simadmin-install.sh uninstall
``` ```
`uninstall` 默认只移除程序源码,保留数据库、Gateway token 和日志。默认安装位置为 `~/Library/Application Support/multi-simadmin`,可通过 `MULTI_SIMADMIN_HOME` 覆盖;额外 LAN Host 可通过 `MULTI_SIMADMIN_ALLOWED_HOSTS`(逗号分隔)配置。 `uninstall` 默认只移除程序源码,保留数据库、Gateway token 和日志。默认安装位置 macOS `~/Library/Application Support/multi-simadmin`Linux 为 `~/.local/share/multi-simadmin`(遵循 XDG),均可通过 `MULTI_SIMADMIN_HOME` 覆盖;额外 LAN Host 可通过 `MULTI_SIMADMIN_ALLOWED_HOSTS`(逗号分隔)配置。
### Fleet 节点总览与跨域健康 ### Fleet 节点总览与跨域健康
+36 -11
View File
@@ -4,7 +4,15 @@ umask 077
REPO_URL=${MULTI_SIMADMIN_REPO_URL:-https://gitea.chickliu.fun/Hermes/multi-simadmin.git} REPO_URL=${MULTI_SIMADMIN_REPO_URL:-https://gitea.chickliu.fun/Hermes/multi-simadmin.git}
PNPM_VERSION="11.13.0" PNPM_VERSION="11.13.0"
APP_ROOT=${MULTI_SIMADMIN_HOME:-"$HOME/Library/Application Support/multi-simadmin"} PLATFORM=$(uname -s)
default_app_root() {
case "$PLATFORM" in
Darwin) printf '%s' "$HOME/Library/Application Support/multi-simadmin" ;;
Linux) printf '%s' "${XDG_DATA_HOME:-$HOME/.local/share}/multi-simadmin" ;;
*) printf '' ;;
esac
}
APP_ROOT=${MULTI_SIMADMIN_HOME:-"$(default_app_root)"}
SOURCE_DIR="$APP_ROOT/source" SOURCE_DIR="$APP_ROOT/source"
DATA_ROOT="$APP_ROOT/data" DATA_ROOT="$APP_ROOT/data"
RUNTIME_DIR="$APP_ROOT/run" RUNTIME_DIR="$APP_ROOT/run"
@@ -29,14 +37,17 @@ Multi SimAdmin 一键安装与服务管理
status 显示进程、端口与健康状态 status 显示进程、端口与健康状态
uninstall 卸载程序,默认保留数据、令牌和日志 uninstall 卸载程序,默认保留数据、令牌和日志
环境变量: 环境变量:
MULTI_SIMADMIN_HOME 安装根目录 MULTI_SIMADMIN_HOME 安装根目录(默认 macOS 为 ~/Library/Application Support/multi-simadminLinux 为 ~/.local/share/multi-simadmin
MULTI_SIMADMIN_ALLOWED_HOSTS 额外允许的 LAN 主机名/IP,逗号分隔 MULTI_SIMADMIN_ALLOWED_HOSTS 额外允许的 LAN 主机名/IP,逗号分隔
MULTI_SIMADMIN_REPO_URL 源码仓库地址 MULTI_SIMADMIN_REPO_URL 源码仓库地址
EOF EOF
} }
require_macos() { require_platform() {
[ "$(uname -s)" = Darwin ] || die "当前生产版仅支持 macOS(秘密存储依赖 macOS Keychain)。" case "$PLATFORM" in
Darwin|Linux) ;;
*) die "当前生产版仅支持 macOS 或 Linux。" ;;
esac
} }
require_commands() { require_commands() {
@@ -61,14 +72,27 @@ pid_owned() {
} }
port_free() { port_free() {
! lsof -nP -iTCP:"$1" -sTCP:LISTEN >/dev/null 2>&1 if command -v lsof >/dev/null 2>&1; then
! lsof -nP -iTCP:"$1" -sTCP:LISTEN >/dev/null 2>&1
elif command -v ss >/dev/null 2>&1; then
! ss -ltn "( sport = :$1 )" 2>/dev/null | grep -q ":$1 "
else
die "缺少 lsof 或 ss,无法检查端口占用"
fi
} }
lan_ip() { lan_ip() {
for interface in en0 en1; do if [ "$PLATFORM" = Darwin ]; then
value=$(ipconfig getifaddr "$interface" 2>/dev/null || true) for interface in en0 en1; do
if [ -n "$value" ]; then printf '%s' "$value"; return; fi value=$(ipconfig getifaddr "$interface" 2>/dev/null || true)
done if [ -n "$value" ]; then printf '%s' "$value"; return; fi
done
else
value=$(ip -4 addr show scope global 2>/dev/null | awk '/inet /{print $2; exit}' | cut -d/ -f1)
if [ -n "${value:-}" ]; then printf '%s' "$value"; return; fi
value=$(hostname -I 2>/dev/null | awk '{print $1}')
if [ -n "${value:-}" ]; then printf '%s' "$value"; return; fi
fi
printf '127.0.0.1' printf '127.0.0.1'
} }
@@ -135,7 +159,7 @@ wait_for() {
} }
start_service() { start_service() {
require_macos require_platform
require_commands require_commands
[ -f "$SOURCE_DIR/apps/web/dist/index.html" ] || die "尚未安装,请先运行 install" [ -f "$SOURCE_DIR/apps/web/dist/index.html" ] || die "尚未安装,请先运行 install"
[ -f "$TOKEN_FILE" ] && [ ! -L "$TOKEN_FILE" ] || die "Gateway token 缺失或不是安全的普通文件,请重新运行 install" [ -f "$TOKEN_FILE" ] && [ ! -L "$TOKEN_FILE" ] || die "Gateway token 缺失或不是安全的普通文件,请重新运行 install"
@@ -192,6 +216,7 @@ start_service() {
trap 'rollback_start' EXIT HUP INT TERM trap 'rollback_start' EXIT HUP INT TERM
MULTI_SIMADMIN_DATA_ROOT="$DATA_ROOT" \ MULTI_SIMADMIN_DATA_ROOT="$DATA_ROOT" \
MULTI_SIMADMIN_DATABASE_PATH="$DATA_ROOT/control-plane.sqlite3" \ MULTI_SIMADMIN_DATABASE_PATH="$DATA_ROOT/control-plane.sqlite3" \
MULTI_SIMADMIN_SECRET_BACKEND="$( [ "$PLATFORM" = Darwin ] && printf macos-keychain || printf secret-file )" \
MULTI_SIMADMIN_GATEWAY_TOKEN="$token" \ MULTI_SIMADMIN_GATEWAY_TOKEN="$token" \
MULTI_SIMADMIN_WEB_DIST="$SOURCE_DIR/apps/web/dist" \ MULTI_SIMADMIN_WEB_DIST="$SOURCE_DIR/apps/web/dist" \
API_HOST=127.0.0.1 API_PORT=8790 \ API_HOST=127.0.0.1 API_PORT=8790 \
@@ -256,7 +281,7 @@ status_service() {
} }
install_app() { install_app() {
require_macos require_platform
require_commands require_commands
mkdir -p "$APP_ROOT" "$DATA_ROOT" "$RUNTIME_DIR" "$LOG_DIR" mkdir -p "$APP_ROOT" "$DATA_ROOT" "$RUNTIME_DIR" "$LOG_DIR"
chmod 700 "$APP_ROOT" "$DATA_ROOT" "$RUNTIME_DIR" "$LOG_DIR" chmod 700 "$APP_ROOT" "$DATA_ROOT" "$RUNTIME_DIR" "$LOG_DIR"