#!/bin/bash # The staging drill rig's startup (docs/runicnpc/PLAN.md D307). Never shipped. # # rust-staging runs the published egg in its vanilla mode. That image's entrypoint always runs # `app_update 258550` before the startup, and the egg cannot be told otherwise, so the server's # startup is this script in front of the egg's own command line: # # bash ./staging-drill.sh ./RustDedicated -batchmode … # # It moves the install to a Steam branch, lays Oxide's build for that branch over it, writes down what # it installed (staging-drill.json), and becomes the server. The branch is `staging` unless the file # staging-drill.branch names another (`public` rehearses the drill on a pair known to match). # tools/drill/drill.js writes this file to the rig as /staging-drill.sh before every start, so the # copy in git is the one that runs. # # Steam keeps the branch: the entrypoint's own app_update, which names none, then answers "already # up to date" and leaves a staging install on staging (seen 2026-10-06). cd /home/container || exit 1 branch=staging if [ -s staging-drill.branch ]; then branch=$(tr -dc 'a-z0-9-' < staging-drill.branch); fi if [ "$branch" = public ]; then OXIDE_URL=https://github.com/OxideMod/Oxide.Rust/releases/latest/download/Oxide.Rust-linux.zip else OXIDE_URL=https://downloads.oxidemod.com/artifacts/Oxide.Rust/$branch/Oxide.Rust-linux.zip fi # The branch Steam has INSTALLED: MountedConfig's key (UserConfig's is only the one asked for). The # public branch has no key. mounted() { sed -n '/"MountedConfig"/,/}/s/^[[:space:]]*"BetaKey"[[:space:]]*"\([^"]*\)".*/\1/p' steamapps/appmanifest_258550.acf | head -1 } # A branch switch downloads the whole server (5.4 GB), and one can fail ("UpdateResult" 13 on # 2026-10-06, the next attempt fine). Rust on one branch with Oxide's build for another dies at boot, # so the server is not started on a pair that does not match. want=$branch [ "$want" = public ] && want="" for attempt in 1 2; do echo "[staging-drill] Rust: app_update 258550 -beta $branch (attempt $attempt)" ./steamcmd/steamcmd.sh +force_install_dir /home/container +login anonymous +app_update 258550 -beta "$branch" +quit installed=$(mounted) [ "${installed:-public}" = "${want:-public}" ] && break done if [ "${installed:-public}" != "${want:-public}" ]; then echo "[staging-drill] Steam installed '${installed:-public}', not '$branch': not starting" exit 1 fi # Oxide's build carries its own patched Assembly-CSharp.dll, so it goes on AFTER Rust. echo "[staging-drill] Oxide: $OXIDE_URL" oxide_modified=$(curl -sSIL "$OXIDE_URL" | tr -d '\r' | sed -n 's/^[Ll]ast-[Mm]odified: //p' | tail -1) if curl -sSL --fail -o oxide-drill.zip "$OXIDE_URL" && unzip -o -q oxide-drill.zip; then oxide_ok=true else oxide_ok=false echo "[staging-drill] Oxide's $branch build could not be installed" fi rm -f oxide-drill.zip buildid=$(sed -n 's/^[[:space:]]*"buildid"[[:space:]]*"\([0-9]*\)".*/\1/p' steamapps/appmanifest_258550.acf | head -1) printf '{"buildid":"%s","branch":"%s","oxideModified":"%s","oxideInstalled":%s,"at":"%s"}\n' \ "$buildid" "${installed:-public}" "$oxide_modified" "$oxide_ok" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > staging-drill.json echo "[staging-drill] $(cat staging-drill.json)" if [ "$oxide_ok" != true ]; then exit 1; fi exec "$@"