#!/usr/bin/env bash set -uo pipefail export TERM=xterm STEAMCMDDIR="${STEAMCMDDIR:-/opt/steamcmd}" VALHEIMDIR="${VALHEIMDIR:-/opt/valheim}" BACKUPDIR="${BACKUPDIR:-/mnt/backups}" BEPINEX_URL="${BEPINEX_URL:-https://cloud.theminisip.ca/index.php/s/K32Lnjc6TyWXaiN/download}" SERVER_NAME="${SERVER_NAME:-Valheim Server}" WORLD_NAME="${WORLD_NAME:-Dedicated}" SERVER_PASSWORD="${SERVER_PASSWORD:-changeme}" PUBLIC="${PUBLIC:-1}" # REQUIRED FIX: remove trailing slash UNITY3D_WORLDS="/root/.config/unity3d/IronGate/Valheim" install_valheim() { echo "[valheim] installing/updating via SteamCMD (forced non-interactive)..." "${STEAMCMDDIR}/steamcmd.sh" \ +force_install_dir "${VALHEIMDIR}" \ +@sSteamCmdForcePlatformType linux \ +login anonymous \ +app_update 896660 validate \ +quit } install_bepinex() { echo "[bepinex] downloading pack..." curl -L "${BEPINEX_URL}" -o /tmp/bepinex.zip echo "[bepinex] validating zip..." if ! unzip -t /tmp/bepinex.zip >/dev/null 2>&1; then echo "[bepinex] ERROR: Downloaded file is not a valid ZIP." exit 1 fi echo "[bepinex] extracting..." rm -rf /tmp/bepinex mkdir -p /tmp/bepinex unzip -q /tmp/bepinex.zip -d /tmp/bepinex bep_root="/tmp/bepinex/BepInExPack_Valheim" if [ ! -d "${bep_root}" ]; then echo "[bepinex] ERROR: Expected folder BepInExPack_Valheim not found." ls -R /tmp/bepinex exit 1 fi echo "[bepinex] copying contents of ${bep_root} to ${VALHEIMDIR}" cp -r "${bep_root}/"* "${VALHEIMDIR}/" sed -i 's/\r$//' "${VALHEIMDIR}/start_server_bepinex.sh" chmod +x "${VALHEIMDIR}/start_server_bepinex.sh" echo "[managed] patching BepInEx password override..." sed -i '/PASSWORD=/d' "${VALHEIMDIR}/start_server_bepinex.sh" sed -i '/changeme/d' "${VALHEIMDIR}/start_server_bepinex.sh" sed -i '/password/d' "${VALHEIMDIR}/start_server_bepinex.sh" echo "[managed] rewriting BepInEx launch command..." sed -i '/exec .*valheim_server.x86_64/d' "${VALHEIMDIR}/start_server_bepinex.sh" cat >> "${VALHEIMDIR}/start_server_bepinex.sh" << EOF exec ./valheim_server.x86_64 \ -name "${SERVER_NAME}" \ -port 2456 \ -world "${WORLD_NAME}" \ -savedir "${UNITY3D_WORLDS}" \ -password "${SERVER_PASSWORD}" \ -public "${PUBLIC}" EOF } install_wrapper() { echo "[managed] installing wrapper script..." cat > "${VALHEIMDIR}/start_server_managed.sh" << EOF #!/usr/bin/env bash set -uo pipefail exec ./start_server_bepinex.sh \ -name "${SERVER_NAME}" \ -port 2456 \ -world "${WORLD_NAME}" \ -password "${SERVER_PASSWORD}" \ -public "${PUBLIC}" EOF chmod +x "${VALHEIMDIR}/start_server_managed.sh" } backup_world() { echo "[backup] backing up world directory..." ts=$(date +"%Y-%m-%d_%H-%M-%S") mkdir -p "${BACKUPDIR}" world_dir="${UNITY3D_WORLDS}/worlds_local/${WORLD_NAME}" if [ -d "${world_dir}" ]; then zip -r "${BACKUPDIR}/${WORLD_NAME}_${ts}.zip" "${world_dir}" echo "[backup] created ${BACKUPDIR}/${WORLD_NAME}_${ts}.zip" else echo "[backup] WARNING: world directory not found: ${world_dir}" fi } install_valheim install_bepinex install_wrapper mkdir -p "${UNITY3D_WORLDS}" || true while true; do sleep 3600 backup_world done & cd "${VALHEIMDIR}" echo "[valheim] starting server..." # REQUIRED FIX: clean exec line exec ./start_server_managed.sh