面板侧的多开方案,把首次部署踩到的坑全部固化,重建不必重新排查。 新增: - mcsm-market.json 自定义市场,3 个端口预排好的 Squad 模板 - scripts/setup-panel.sh 幂等的面板配置脚本(装 Docker/登录私有仓库/ 开启 enableApiKey 与 allowUsePreset/指向自建市场) - scripts/squad-instance.py 按实例号自动排布端口的实例管理脚本(已实测) - scripts/mcsm.py 通用 API 封装 - PANEL.md 面板侧文档 修正官方 Squad 模板的三个致命问题(均已实测): - image 指向 Docker Hub,在受限网络下必然 i/o timeout - networkMode 为 bridge,Squad 依赖 Steam 查询协议,该模式下 服务端能起但游戏内浏览器搜不到;且端口映射漏了查询口与 RCON 口 - startCommand 不带端口参数,多开时第二个实例会抢第一个的端口 记录两个文档未提及的面板开关:enableApiKey 与 allowUsePreset 默认均为 false,前者会让所有 apikey 请求返回 403;以及 session 鉴权除 cookie 外 还需把 token 作为 query 参数带上。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
201 lines
6.8 KiB
Markdown
201 lines
6.8 KiB
Markdown
# 用 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`(控制台日志会打印
|
|
`已挂载工作目录:<cwd> --> /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=<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 <uuid>
|
|
```
|
|
|
|
端口按实例号自动计算,不用手工算也不会撞。
|
|
|
|
---
|
|
|
|
## 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`,
|
|
普通用户登录过不算
|