# 用 MCSManager 面板管理 Squad 多实例 配合 `scripts/setup-panel.sh` 与 `mcsm-market.json` 使用。 **为什么需要这份文档**:MCSManager 官方市场里自带一个 Squad Docker 模板,但它在 「无法访问 Docker Hub 的环境 + 多实例」场景下**必然失败**,且失败信息不指向真正原因。 下面每一条都是实测踩出来的。 --- ## 1. 一键重建 ```bash export ACR_REGISTRY=<你的镜像仓库> export ACR_USERNAME=<用户名> export ACR_PASSWORD=<密码> # 不要写进任何文件 export MARKET_URL=http://<你的 gitea>/xiaohei/squaddocker/raw/branch/main/mcsm-market.json sudo -E ./scripts/setup-panel.sh ``` 脚本幂等,可重复执行。已装过面板时用 `--skip-install` 只应用配置修正。 --- ## 2. 官方模板的三个致命问题 `market-v2.json` 里 `packages[0]` 是官方的 "Squad Docker Server": | 官方模板 | 问题 | 后果 | |---|---|---| | `image: githubyumao/steam-game-runtime:latest` | 从 Docker Hub 拉 | 大陆网络下 `i/o timeout`,实例创建直接失败 | | `networkMode: bridge` + `ports` 映射 | Squad 依赖 Steam 查询协议 | 服务端能起,但**游戏内浏览器搜不到服务器** | | `startCommand: ./SquadGameServer.sh` | 不带任何端口参数 | 多开时第二个实例抢第一个的端口 | 官方模板的端口映射还漏了两个端口:只映射了 `7787/udp` 和 `15000/udp`, **缺少 Steam 查询端口 `27165` 和 RCON 端口 `21114`**。 `mcsm-market.json` 修正了以上全部,并预排了 3 个实例的端口。 --- ## 3. 面板配置的两个隐藏开关 两个都默认关闭,而且 API 文档没提: ```jsonc // /opt/mcsmanager/web/data/SystemConfig/config.json { "enableApiKey": false, // ← 不开,所有 apikey 请求返回 403 "allowUsePreset": false, // ← 不开,UI 里看不到市场/快速部署入口 "presetPackAddr": "https://script.mcsmanager.com/market-v2.json" // ← 可指向自建市场 } ``` 改完必须 `systemctl restart mcsm-web`。 `enableApiKey=false` 时的报错原文: ``` The administrator has disabled the use of the API key. Please contact the administrator and set "enableApiKey" to "true" in the configuration file to enable normal use of the API endpoints. ``` --- ## 4. API 鉴权的两条路,别混用 **apikey**(适合脚本):query 参数 `?apikey=xxx`,需要 `enableApiKey=true`。 **session**(适合模拟浏览器):`POST /api/auth/login` 拿到 token 后, **除 cookie 外还要把 token 作为 query 参数 `?token=xxx` 带上**, 否则返回 `令牌(Token)验证失败,拒绝访问`。这一点文档没写。 两种方式都必须带请求头: ``` X-Requested-With: XMLHttpRequest Content-Type: application/json; charset=utf-8 ``` > 文档里有一句要当真:「提交所有参数,即使参数未定义,否则有概率触发 bug」。 > 改配置时要 GET 出完整配置、改字段、再整体 PUT 回去,不要只提交想改的那几个键。 --- ## 5. 首次创建管理员 面板装好后是**零账号状态**(日志 `Number of local users: 0`), 没有初始密码,首次访问由访问者在浏览器里自行注册管理员。 > ⚠️ 这意味着**谁先访问谁就是管理员**。放行安全组后请立即完成初始化, > 并把安全组来源限制成自己的 IP。 一次性接口是 `POST /api/auth/install`,装好后不可重复调用 (面板会返回「面板已安装,无法重复安装」)。 --- ## 6. 创建实例后必做的两步 模板只能配到面板这一层,剩下两步在服务端: **① 建数据目录** ```bash sudo mkdir -p /srv/squad/instN sudo chown -R 1000:1000 /srv/squad/instN ``` 面板会把实例的 `cwd` 挂载到容器内 `/data`(控制台日志会打印 `已挂载工作目录: --> /data`)。若目录已有游戏文件,SteamCMD 会 输出「跳过下载」直接复用 —— 迁移实例时可以靠这个省掉 14GB 重下。 **② 设置 RCON 密码** 首启会下载约 14GB 游戏本体(实测十几分钟)。下载完成后: ```bash sudo sed -i -E 's/^Password=.*$/Password=<你的密码>\r/' \ /srv/squad/instN/SquadGame/ServerConfig/Rcon.cfg ``` - `Rcon.cfg` 是 **CRLF 行尾**,末尾 `\r` 要保留 - 密码为空时**服务端不会启动 RCON**,表现为 RCON 端口不监听。 容易误判成端口冲突,实际日志是: ``` LogRCONServer: Warning: RCONServer was not setup because the password was not specified on the command line or in the ini file ``` 设置成功后应看到 `LogRCONServer: Start(): RCONServer setup on 0.0.0.0:21114` - 该密码要与面板实例配置里的 `rconPassword` **一致**,否则面板连不上 RCON --- ## 7. 端口规划 游戏端口和查询端口**各占 `N` 和 `N+1` 两个**,所以实例间隔取 10。 | 实例 | 游戏 | 查询 | Beacon | RCON | |---|---|---|---|---| | 1 | 7787 / 7788 | 27165 / 27166 | 15000 | 21114 | | 2 | 7797 / 7798 | 27175 / 27176 | 15010 | 21124 | | 3 | 7807 / 7808 | 27185 / 27186 | 15020 | 21134 | `BEACONPORT` 最容易漏 —— 官方 wiki 的服务器安装页完全没提, 但 host 网络下两个实例都会去绑它,导致第二个实例行为异常且日志不明确。 安全组只需放行游戏端口和查询端口。**RCON 端口不要对全网开放**, 它是远程管理通道。 --- ## 8. 用脚本批量创建(替代 UI) ```bash export MCSM_URL=http://<面板>:23333 export MCSM_APIKEY= export MCSM_DAEMON=$(./scripts/squad-instance.py list-daemons | awk '{print $1}' | cut -d= -f2) ./scripts/squad-instance.py create 4 # 端口自动排到 7817/27195/15030/21144 ./scripts/squad-instance.py list ./scripts/squad-instance.py start ``` 端口按实例号自动计算,不用手工算也不会撞。 --- ## 9. 硬件底线 单实例实测内存峰值 **5.26 GiB**(零玩家状态),所以: | | 单实例 | 双实例 | |---|---|---| | 物理核 | 1 | **2**(看物理核不是 vCPU,Squad 主 tick 重度单线程) | | 内存 | 8 GB | **16 GB** | | 磁盘 | 20 GB | 40 GB(每实例约 14GB 游戏文件) | `docker.memory` 必须设(模板里是 6144 MB)。设成 `0` 表示无上限, 小内存机器会被容器 OOM 拖垮整机。宿主机若无 swap,建议加 4GB: ```bash sudo fallocate -l 4G /swapfile && sudo chmod 600 /swapfile sudo mkswap /swapfile && sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab ``` --- ## 10. 已知问题 - **`RANDOM` 环境变量在 `cm2network/squad` 镜像中无效**。`RANDOM` 是 bash 内置 特殊变量,环境变量覆盖不了它,实机确认传给服务端的是随机整数 (如 `RANDOM=10257`)。地图轮换请用 `MapRotation.cfg`。详见 README §10.1 - 官方备用下载源 `download.mcsmanager.com` **TLS 证书域名不匹配**, 主源不通时该备用源不可信 - 面板 `daemon` 以 **root** 运行。私有仓库需要用 root 身份 `docker login`, 普通用户登录过不算