Files
squaddocker/PANEL.md
T
gongzhiyongandClaude Opus 5 fe256c619f feat: 新增 MCSManager 面板集成 —— 自定义市场模板与一键配置脚本
面板侧的多开方案,把首次部署踩到的坑全部固化,重建不必重新排查。

新增:
- 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>
2026-07-27 21:40:09 +08:00

6.8 KiB

用 MCSManager 面板管理 Squad 多实例

配合 scripts/setup-panel.sh 与 mcsm-market.json 使用。

为什么需要这份文档:MCSManager 官方市场里自带一个 Squad Docker 模板,但它在 「无法访问 Docker Hub 的环境 + 多实例」场景下必然失败,且失败信息不指向真正原因。 下面每一条都是实测踩出来的。


1. 一键重建

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 文档没提:

// /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. 创建实例后必做的两步

模板只能配到面板这一层,剩下两步在服务端:

① 建数据目录

sudo mkdir -p /srv/squad/instN
sudo chown -R 1000:1000 /srv/squad/instN

面板会把实例的 cwd 挂载到容器内 /data(控制台日志会打印 已挂载工作目录:<cwd> --> /data)。若目录已有游戏文件,SteamCMD 会 输出「跳过下载」直接复用 —— 迁移实例时可以靠这个省掉 14GB 重下。

② 设置 RCON 密码

首启会下载约 14GB 游戏本体(实测十几分钟)。下载完成后:

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)

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:

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, 普通用户登录过不算