面板侧的多开方案,把首次部署踩到的坑全部固化,重建不必重新排查。 新增: - 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>
163 lines
7.5 KiB
Bash
Executable File
163 lines
7.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# MCSManager + Squad 一键配置脚本(幂等,可重复执行)
|
|
#
|
|
# 把首次部署踩到的所有坑固化在这里,重建时不用再排查一遍。
|
|
# 每一处 fix 都标注了「不做会怎样」。
|
|
#
|
|
# 用法:
|
|
# sudo ./setup-panel.sh # 全流程
|
|
# sudo ./setup-panel.sh --skip-install # 面板已装,只应用修正
|
|
#
|
|
# 需要的环境变量(镜像仓库凭据,不要写进脚本):
|
|
# ACR_REGISTRY 如 squaddocker.azurecr.cn
|
|
# ACR_USERNAME
|
|
# ACR_PASSWORD
|
|
# MARKET_URL 自定义市场 JSON 的地址(见仓库 mcsm-market.json)
|
|
|
|
set -euo pipefail
|
|
|
|
CONFIG=/opt/mcsmanager/web/data/SystemConfig/config.json
|
|
SKIP_INSTALL=0
|
|
[[ "${1:-}" == "--skip-install" ]] && SKIP_INSTALL=1
|
|
|
|
[[ $EUID -eq 0 ]] || { echo "需要 root: sudo $0"; exit 1; }
|
|
|
|
log() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; }
|
|
warn() { printf '\033[1;33m[!] %s\033[0m\n' "$*"; }
|
|
|
|
# ─────────────────────────────────────────────────────────────
|
|
log "1/6 安装 Docker(若未安装)"
|
|
# 坑:Ubuntu 上 apt install docker.io 的 Candidate 可能是 (none),
|
|
# 必须走 Docker 官方源。
|
|
if ! command -v docker >/dev/null; then
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -qq
|
|
apt-get install -y -qq ca-certificates curl gnupg
|
|
install -m 0755 -d /etc/apt/keyrings
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
|
chmod a+r /etc/apt/keyrings/docker.asc
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
|
|
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
|
|
> /etc/apt/sources.list.d/docker.list
|
|
apt-get update -qq
|
|
apt-get install -y -qq docker-ce docker-ce-cli containerd.io \
|
|
docker-buildx-plugin docker-compose-plugin
|
|
systemctl enable --now docker
|
|
else
|
|
echo " 已安装: $(docker --version)"
|
|
fi
|
|
|
|
# ─────────────────────────────────────────────────────────────
|
|
log "2/6 配置 dockerd 日志轮转"
|
|
# 坑:Squad 日志量大,不轮转会占满磁盘。
|
|
if [[ ! -f /etc/docker/daemon.json ]] || ! grep -q max-size /etc/docker/daemon.json; then
|
|
mkdir -p /etc/docker
|
|
[[ -f /etc/docker/daemon.json ]] && cp /etc/docker/daemon.json /etc/docker/daemon.json.bak
|
|
cat > /etc/docker/daemon.json <<'EOF'
|
|
{
|
|
"log-driver": "json-file",
|
|
"log-opts": { "max-size": "50m", "max-file": "3" }
|
|
}
|
|
EOF
|
|
systemctl restart docker
|
|
echo " 已配置并重启 dockerd"
|
|
else
|
|
echo " 已配置,跳过"
|
|
fi
|
|
|
|
# ─────────────────────────────────────────────────────────────
|
|
log "3/6 登录私有镜像仓库并预拉镜像"
|
|
# 坑:目标机若访问不了 Docker Hub,官方市场模板里的镜像必然拉取超时。
|
|
# 必须先把镜像搬到私有仓库。
|
|
# 坑:MCSManager daemon 以 root 运行,所以必须用 root 的身份 docker login,
|
|
# 普通用户登录过不算。
|
|
if [[ -n "${ACR_REGISTRY:-}" && -n "${ACR_PASSWORD:-}" ]]; then
|
|
printf '%s' "$ACR_PASSWORD" | docker login "$ACR_REGISTRY" \
|
|
-u "${ACR_USERNAME:?需要 ACR_USERNAME}" --password-stdin
|
|
docker pull "$ACR_REGISTRY/steam-game-runtime:latest" || \
|
|
warn "预拉镜像失败,面板首次启动实例时会现拉(可能超时)"
|
|
else
|
|
warn "未设置 ACR_* 环境变量,跳过镜像仓库登录。"
|
|
warn "若目标机无法访问 Docker Hub,实例创建会失败。"
|
|
fi
|
|
|
|
# ─────────────────────────────────────────────────────────────
|
|
log "4/6 安装 MCSManager"
|
|
if [[ $SKIP_INSTALL -eq 1 ]]; then
|
|
echo " --skip-install,跳过"
|
|
elif [[ -d /opt/mcsmanager ]]; then
|
|
echo " /opt/mcsmanager 已存在,跳过安装"
|
|
else
|
|
# 官方脚本会自带 Node(不污染系统 Node),建立 mcsm-web / mcsm-daemon 两个
|
|
# systemd 服务并自动 enable。建议先下载审阅再执行,不要直接管道到 bash。
|
|
curl -fsSL https://script.mcsmanager.com/setup.sh -o /tmp/mcsm-setup.sh
|
|
echo " 已下载安装脚本到 /tmp/mcsm-setup.sh ($(wc -l < /tmp/mcsm-setup.sh) 行)"
|
|
echo " 建议先审阅再继续。按 Enter 执行,Ctrl-C 中止。"
|
|
read -r _
|
|
bash /tmp/mcsm-setup.sh
|
|
fi
|
|
|
|
# ─────────────────────────────────────────────────────────────
|
|
log "5/6 应用面板配置修正"
|
|
[[ -f "$CONFIG" ]] || { echo "找不到 $CONFIG,面板可能未装好"; exit 1; }
|
|
cp -n "$CONFIG" "$CONFIG.orig" 2>/dev/null || true
|
|
|
|
python3 - "$CONFIG" "${MARKET_URL:-}" <<'PY'
|
|
import json, sys, pathlib
|
|
cfg_path, market_url = pathlib.Path(sys.argv[1]), sys.argv[2]
|
|
d = json.loads(cfg_path.read_text())
|
|
changes = []
|
|
|
|
# 坑:apikey 默认被禁用,API 文档通篇讲怎么用 apikey 却没提这个开关。
|
|
# 不开的话所有 API 调用返回 403 "administrator has disabled the use of the API key"。
|
|
if not d.get("enableApiKey"):
|
|
d["enableApiKey"] = True; changes.append("enableApiKey -> true")
|
|
|
|
# 坑:预设(市场模板)功能默认关闭,UI 里看不到快速部署入口。
|
|
if not d.get("allowUsePreset"):
|
|
d["allowUsePreset"] = True; changes.append("allowUsePreset -> true")
|
|
|
|
# 官方市场里的 Squad 模板有三个问题:镜像指向 Docker Hub、networkMode 是
|
|
# bridge(Squad 必须 host,否则游戏内浏览器搜不到服务器)、startCommand
|
|
# 不带端口参数(多开时第二个实例会抢第一个的端口)。
|
|
# 指向自建市场以修正这三点。
|
|
if market_url and d.get("presetPackAddr") != market_url:
|
|
d["presetPackAddr"] = market_url
|
|
changes.append(f"presetPackAddr -> {market_url}")
|
|
|
|
if changes:
|
|
cfg_path.write_text(json.dumps(d, indent=2, ensure_ascii=False))
|
|
for c in changes: print(f" {c}")
|
|
else:
|
|
print(" 配置已是目标状态,无需改动")
|
|
PY
|
|
|
|
systemctl restart mcsm-web
|
|
sleep 5
|
|
systemctl is-active mcsm-web >/dev/null && echo " mcsm-web 已重启" || warn "mcsm-web 未启动"
|
|
|
|
# ─────────────────────────────────────────────────────────────
|
|
log "6/6 完成"
|
|
cat <<'EOF'
|
|
|
|
面板端口: 23333/TCP(Web) 24444/TCP(Daemon)
|
|
|
|
安全提醒:
|
|
· 只在云安全组放行 23333,且建议限制来源 IP。
|
|
24444 是 Daemon 的远程执行接口,放行等于把它开到互联网。
|
|
· 面板是 HTTP 明文,登录密码裸传。需要 HTTPS 请另配反向代理。
|
|
· 首次访问前面板处于零账号状态,谁先打开谁就能注册成管理员 ——
|
|
放行安全组后请立即完成初始化,不要搁置。
|
|
|
|
创建 Squad 实例后还需两步(否则起不来或 RCON 不可用):
|
|
1) 建数据目录: mkdir -p /srv/squad/instN && chown -R 1000:1000 /srv/squad/instN
|
|
2) 首启会下载约 14GB 游戏本体。下载完成后设置 RCON 密码:
|
|
sed -i -E 's/^Password=.*$/Password=<你的密码>\r/' \
|
|
/srv/squad/instN/SquadGame/ServerConfig/Rcon.cfg
|
|
Rcon.cfg 是 CRLF 行尾,末尾的 \r 要保留。
|
|
密码为空时服务端不会启动 RCON,表现为 RCON 端口不监听
|
|
(日志: "RCONServer was not setup because the password was not specified")。
|
|
该密码要和面板实例配置里的 rconPassword 一致。
|
|
|
|
EOF
|