Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ services:
- windrose
entrypoint: ["python3", "/opt/windrose-ui/server.py"]
environment:
UI_BIND: ${UI_BIND:-127.0.0.1}
UI_BIND: "0.0.0.0"
UI_PORT: ${UI_PORT:-28080}
UI_PASSWORD: ${UI_PASSWORD:-}
# Opt-in: allow destructive actions when no password is set (LAN-only).
Expand Down
66 changes: 44 additions & 22 deletions scripts/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,10 @@ install_via_steamcmd() {
# debugging corruption. Default off; set WINDROSE_STEAMCMD_VALIDATE=1
# to enable. Also forced on if we see a partial install (dir exists but
# binary missing).
local validate_arg=""
if [ "${WINDROSE_STEAMCMD_VALIDATE:-0}" = "1" ]; then
validate_arg="validate"
elif [ -d "${WINDROSE_SERVER_DIR}" ] \
&& [ ! -f "${WINDROSE_SERVER_DIR}/R5/Binaries/Win64/WindroseServer-Win64-Shipping.exe" ] \
&& [ -n "$(ls -A "${WINDROSE_SERVER_DIR}" 2>/dev/null)" ]; then
# Partial install detected; force validate to clean it up.
validate_arg="validate"
fi
# Always pass `validate` to app_update. Costs ~30s on a populated
# 3 GB tree (re-checksum, no download), gives us idempotent install
# health on every boot, and matches the official Windrose FAQ
# command. Not worth conditionalizing.

# Stash under WINDROSE_PATH (on the PVC), NOT /tmp — /tmp is
# container-ephemeral, so a kubelet OOM-kill / eviction / node
Expand Down Expand Up @@ -196,20 +191,47 @@ install_via_steamcmd() {
fi
done

echo "$(timestamp) INFO: SteamCMD +app_update ${app_id} ${validate_arg:-(no-validate)}"
mkdir -p "${WINDROSE_SERVER_DIR}"
# Arg order matters: +force_install_dir MUST precede +login anonymous.
# Valve's client literally prints "Please use force_install_dir before
# logon!" and fails app_update with "Missing configuration" otherwise.
# (Caught on an Ubuntu 24.04 bare-Linux install where the order-invert
# was a hard failure; Debian-13-in-container happens to tolerate the
# wrong order sometimes but don't count on it.)
local rc=0
"${STEAMCMD_PATH}/steamcmd.sh" \
+force_install_dir "${WINDROSE_SERVER_DIR}" \
+login anonymous \
+app_update "${app_id}" ${validate_arg} \
+quit || rc=$?
# SteamCMD's anonymous app_update is flaky on the first attempt
# within a container — fails with "ERROR! Failed to install app
# '4129620' (Missing configuration)" + exit 8 (which the script
# confusingly still reports as exit 0 sometimes), then succeeds on
# the very next attempt with no other change. Verified clean-room
# 2026-04-27: attempt #1 FAIL, #2 OK + downloads, #3 resumes at
# whatever % #2 reached. Probably a Steam-side anonymous-license
# caching quirk that warms up after the first call. Retry up to 3
# times; each attempt resumes the partial download so we don't pay
# the bandwidth twice.
#
# Existing populated installs are unaffected — verify-only runs
# don't go through the failing licensing path. So canary / prod /
# VPS kept working, masking the regression for fresh-install
# operators.
#
# Stdin heredoc instead of +command-line chain — the two are
# roughly equivalent, but heredoc reads more like the official
# Windrose / Steam dedicated-server FAQ examples that operators
# paste into interactive SteamCMD when debugging.
local rc=1
local attempt
for attempt in 1 2 3; do
echo "$(timestamp) INFO: SteamCMD app_update ${app_id} validate (attempt ${attempt})"
rc=0
"${STEAMCMD_PATH}/steamcmd.sh" <<EOF || rc=$?
force_install_dir ${WINDROSE_SERVER_DIR}
login anonymous
app_update ${app_id} validate
quit
EOF
if server_files_present; then
rc=0
break
Comment on lines +226 to +228

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep non-zero SteamCMD exits from being treated as success

In install_via_steamcmd, this success check promotes any run to success as soon as the server binary exists, but on populated installs that binary already exists before app_update starts (only Saved/ and JSON are stashed). If SteamCMD fails with a non-zero exit due to transient Steam/network issues, this block sets rc=0 and breaks anyway, so the script logs a successful install while silently skipping the update; after game patches this can leave the server on a stale build and cause client version mismatch failures.

Useful? React with 👍 / 👎.

fi
if [ "${attempt}" -lt 3 ]; then
echo "$(timestamp) WARNING: SteamCMD app_update attempt ${attempt} did not produce server binary; retrying"
sleep 2
fi
done

echo "$(timestamp) INFO: Restoring identity + save from ${preserve_dir}"
mkdir -p "${WINDROSE_SERVER_DIR}/R5"
Expand Down
Loading