Files
7dtd-ul-bootstrap/bootstrap.sh
2025-09-15 23:10:15 +00:00

361 lines
14 KiB
Bash

#!/usr/bin/env bash
# prefer to target .sh over BASH for wider compatibility
# Designed for and tested on Ubuntu 24.04 LXC on Proxmox host
# Using Proxmox Ubuntu 24.04 Standard AMD64 template
# Prerequisites:
# 1. Download Ubuntu 24.04 Standard AMD64 LXC template
# 2. Create new LXC
# - Minimum 4 cores
# - Minimum 12GB RAM, 16GB recommended
# - Minimum 32GB Disk space
# - Recommend 64GB disk space or 24GB with additional mapped storage
# - Unpriviliged container is acceptable
# - AMD64 architecture
# - Use 'ubuntu-24.04-standard_24.04-[any]_amd64' template
# 3. Boot container and connect to shell
# 4. Configure locales: `root@7dtd:~# dpkg-reconfigure tzdata`
# 5. Update Ubuntu: `root@7dtd:~# apt update && apt upgrade -y`
# 6. Reboot: `root@7dtd:~# reboot`
# 7. Download and modify the settings template
# - `root@7dtd:~# wget xx.yy.zz/ul-bootstrap.conf`
# - `root@7dtd:~# nano ul-bootstrap.conf`
# 8. Download and run the bootstrap script
# - `root@7dtd:~# wget xx.yy.zz/bootstrap.sh`
# check if root
if [ "$EUID" -ne 0 ]; then
echo "Must be run as root"
exit
fi
set -eu
if [ ! -z ${DEV+x} ] && [ "$DEV" -eq "1" ]; then
# enable early debugging with `DEV=1 build.sh`
set -x
PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
else
set -eu
fi
__SCRIPTARGS="$*"
__SCRIPTNAME="devenv.sh"
__SCRIPTFULLNAME="$0"
# Common variables and functions
_TRUE=1
_FALSE=0
# DOWNLOADS: Directory where build script will cache downloaded files
DOWNLOADS="${DOWNLOADS:-download}"
# TMP: Temporary working directory used by build script
TMP="${TPM:-tmp}"
# DEV_DIR: Directory where development environment is set up
DEV_DIR="${DEV_DIR:-dev}"
# OUT: Output directory for files generated by the script for the project
OUT="${OUT:-out}"
# OUT_FILES: List of files generated by these scripts
OUT_FILES="${OUT_FILES:-bl_update_payload}"
# name of BUP file generated by Nvidia script
BUPFILE="${BUPFILE:-bl_update_payload}"
# UPDATE_SCRIPT: Name of final update file used to distribute updates to Nano
UPDATE_SCRIPT="${UPDATE_SCRIPT:-czup.sh}"
#===============================================================================
#===== FUNCTIONS =====
#===============================================================================
#--- FUNCTION ----------------------------------------------------------------
# NAME: __cleanup
# DESCRIPTION: Cleanup temporary files; disabled when devmode=true
# USAGE: __cleanup
#-------------------------------------------------------------------------------
__cleanup() {
if [ "$_DEV" -eq "$_FALSE" ]; then
O_DIR="$(pwd)"
cd "${WORK_DIR}"
if [ -e "${TMP}" ]; then
echo "Removing temporary files..."
__sudo rm -rf "${TMP}"
fi
#if [ -e "Linux_for_Tegra" ]; then
# echo "Removing Linux_for_Tegra directory..."
# rm -rf "Linux_for_Tegra"
#fi
if [ -e "devicetree_binaries.tgz" ]; then
__sudo rm "devicetree_binaries.tgz"
fi
if [ -e "tpm.tgz" ]; then
__sudo rm "tpm.tgz"
fi
if [ -e "tpm-rng.tgz" ]; then
__sudo rm "tpm-rng.tgz"
fi
if [ -e "${BUPFILE}" ]; then
__sudo rm "${BUPFILE}"
fi
if [ -e "Module.symvers" ]; then
__sudo rm "Module.symvers"
fi
cd "${O_DIR}"
fi
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: __check_command_exists
# DESCRIPTION: Check if a command exists.
# USAGE: if [!] (__check_command_exists [command]); then
#-------------------------------------------------------------------------------
__check_command_exists() {
command -v "$1" > /dev/null 2>&1
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: __sudo
# DESCRIPTION: Perform action as root.
# USAGE: __sudo cp $a $b
#-------------------------------------------------------------------------------
__sudo() {
sudo "$@"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: __env
# DESCRIPTION: Print the environment variables to output
# USAGE: __env
#-------------------------------------------------------------------------------
__env() {
#echo "$(printenv)"
#comm -3 <(comm -3 <(declare | sort) <(declare -f | sort)) <(env | sort)
diff <(bash -cl 'set -o posix && set') \
<(set -o posix && set && set +o posix) | \
grep -E "^>|^\+" | \
grep -Ev "^(>|\+|\+\+) ?(BASH|COLUMNS|LINES|HIST|PPID|SHLVL|PS(1|2)|SHELL|FUNC)" | \
sed -r 's/^> ?|^\+ ?//'
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: __wget
# DESCRIPTION: Download if file doesn't exist.
# USAGE: __wget [outfile] [url]
# NOTES: if [outfile] exists, it will be tested to verify it is a regular file
#-------------------------------------------------------------------------------
__wget() {
# check usage
if [ -z "${1}" ] || [ -z "${2}" ]; then
echo "__wget function usage:"
echo " \$ __wget [outfile] [url]"
exit 1
fi
# Create the DOWNLOADS directory if it doesn't already exist
if [ ! -d "${DOWNLOADS}" ]; then
mkdir -p "${DOWNLOADS}" || ( echo "error creating \"${DOWNLOADS}\" directory" && exit 1 )
fi
# test if [outfile] exists but is not a regular file
# ie: [outfile] is device, directory, link, etc
if [ -e "${DOWNLOADS}/${1}" ] && [ ! -f "${DOWNLOADS}/${1}" ]; then
echo "__wget: [outfile] \"${DOWNLOADS}/${1}\" exists, but is not a regular file"
exit 1
fi
# download [outfile] if it doesn't already exist
if [ ! -e "${DOWNLOADS}/${1}" ]; then
if ! (__check_command_exists wget); then
__sudo apt-get update || ( echo "Unable to update apt packages" && exit 1 )
__sudo apt-get install wget || ( echo "Unable to install wget" && exit 1 )
fi
if [ -f "../${DOWNLOADS}/${1}" ]; then
echo "Copying ${1}"
cp -v "../${DOWNLOADS}/${1}" "${DOWNLOADS}/${1}" || ( echo "error copying ${1} from parent directory" && exit 1 )
else
echo "Downloading ${1}"
wget -q --show-progress -O "${DOWNLOADS}/${1}" "${2}" || ( echo "error downloading ${1}" && exit 1 )
fi
fi
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: realpath
# DESCRIPTION: Cross-platform realpath command. Because Mac.
#-------------------------------------------------------------------------------
realpath() {
perl -e 'use Cwd "abs_path";print abs_path(shift)' "$1"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: __usage
# DESCRIPTION: Display program help
# USAGE: __usage
#-------------------------------------------------------------------------------
__usage() {
cat << EOT
Usage: ${__SCRIPTNAME} [options] [action]...
Actions:
- dtb Build Devicetree binary files
- blob Build Mass Flash tool to flash Nano over USB
- bup Build Bootloader Update Package
- tpm Build the TPM kernel modules
- tpm-rng Build the TPM hardware random number generator module
- pkg Build the update package to distribute to Nano
- dev Enable development (debug) mode. Mainly, disables cleanup of
temporary files created during program execution
- all Same as ${__SCRIPTNAME} dtb bup tpm pkg blob
Does not build the optional tpm-rng module
- env Print list of variables and their values
- help Display usage
Options:
-h Display this help
-D Enable debugging mode
Examples:
- ${__SCRIPTNAME} all
- ${__SCRIPTNAME} all dev
- ${__SCRIPTNAME} dtb tpm bup
EOT
}
#===============================================================================
#===== BEGIN =====
#===============================================================================
# cleanup existing temporary working directories; force regardless of _DEV option
_DEV=$_FALSE __cleanup
mkdir -p "${TMP}"
#-------------------------------------------------------------------------------
#----- Command Line Args -----
#-------------------------------------------------------------------------------
_BLOB=${BLOB:-$_FALSE}
_BUP=${BUP:-$_FALSE}
_DTB=${DTB:-$_FALSE}
_TPM=${TPM:-$_FALSE}
_TPMRNG=${TPMRNG:-$_FALSE}
_DEV=${DEV:-$_FALSE}
_PKG=${PKG:-$_FALSE}
# default option all if no options or actions specified
if [ $# -eq 0 ]; then
set -- "all"
fi
# restrict $_DEV values to $_TRUE or $_FALSE
if [ "$_DEV" -eq "$_TRUE" ]; then
_DEV=$_TRUE
else
_DEV=$_FALSE
fi
while getopts 'Dh-:' OPT; do
# support long options: https://stackoverflow.com/a/28466267/519360
if [ "$OPT" = "-" ]; then # long option: reformulate opt and optarg
OPT="${OPTARG%%=*}" # extract long option name
OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty)
OPTARG="${OPTARG#=}" # if long option argument, remove assigning '='
fi
case "${OPT}" in
D ) echo "DEVELOPER MODE ENABLED"; _DEV=$_TRUE ;;
h | help ) __usage; rm -rf "${TMP}"; exit 0 ;;
??* ) die "Illegal option --$OPT" ;; # bad long option
? ) exit 2 ;; # bad short option (error reported via getopts)
esac
done
shift $((OPTIND-1))
while [[ "$#" -gt 0 ]]; do
case $1 in
env ) __env ;;
all ) _DTB=$_TRUE; _BUP=$_TRUE; _TPM=$_TRUE; _PKG=$_TRUE; _BLOB=$_TRUE ;;
dtb ) _DTB=$_TRUE ;;
bup ) _BUP=$_TRUE ;;
tpm ) _TPM=$_TRUE ;;
pkg ) _PKG=$_TRUE ;;
tpm-rng ) _TPMRNG=$_TRUE ;;
dev ) _DEV=$_TRUE ;;
help | --help ) __usage; exit 0 ;;
esac
shift
done
# Configure environment for debugging
if [ "$_DEV" -eq "$_TRUE" ]; then
set -x
PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
else
set -eu
fi
# TODO: bootstrap system from here
#
# 7dtd.sh package prerequisites described here: https://7dtd.illy.bz/wiki/Prerequisites
#
# verify packages:
# - xmlstarlet
# - expect
# - lib32gcc-s1
# - lib32stdc++6
# - make
# - gcc
#
# Should be available, but verify may be a good idea:
# - wget
# - rsync
# - pkill
# - netstat
# - bash
# - init system: either SysVInit or systemd
# - cut, tr, tail, stdbuf
# - grep, sed, dd, date, mkdir, touch, nc
#
# Should be compiled and installed from bootstrap:
# - start-stop-daemon
#
#
# Modify the 7dtd.illy script for our purposes
# -
#
# Additional steps notes - unordered list
# - Install steamcmd
# - Install 7dtd Alpha 20.7
# - Download Undead Legacy
# - Correct version for a20.7b1 is UL 2022.11.25 - 2.6.17
# - URL: https://ul.subquake.com/dl?v=stable
# - default 'UndeadLegacyStable-main.zip'
# - wget -O ul-20221125-v2.6.17.zip https://ul.subquake.com/dl?v=stable
# - Script version v.115 is the historical version originally in use during Alpha 20
# - If using v.115, incorporate necessary future version features
# - v.116 added pygmentize feature for printxml to print serverconfig.xml
# - Current revision is v.118. v.118 might be usable or patchable for our purposes
# - Enable bash completion
# - Download the correct illy server fixes mod
# - Per https://7dtd.illy.bz/wiki/Server%20fixes#a7DaystoDievsModversioncompatibility
# - Correct version for Alpha 20.7 b1 is Mod version 22_24_39, SVN rev 370
# - URL: https://illy.bz/fi/7dtd/server_fixes_v22_24_39.tar.gz
# - Extract UL to 7dtd engine directory (parent to Mods)
# - copy BepInEx from .zip to engine/BepInEx
# - copy Mods from .zip to engine/Mods
# - copy doorstop_libs from .zip to engine/doorstop_libs
# - copy doorstop_config.ini from .zip to engine/doorstop_config.ini
# - copy run_bepinex_server.sh from .zip to engine/run_bepinex_server.sh
# - Might also need to add <dllmap dll="dl" target="libdl.so.2"/> to 7DaysToDieServer_Data/MonoBleedingEdge/etc/mono/config
# - see https://ul.subquake.com/servers under Dedicated Server - Linux
# - Create the serverconfig.xml, admins.xml, 7dtd.conf
#
# - Install steamcmd
# - install 7dtd a20.7b1
# - install 7dtd.sh
# - create 7dtd.conf
# - install allocs server fixes
# - install undead legacy
# - configure server instance compatible with 7dtd.sh server manager
# - create serverconfig.xml
# - create admins.xml
#
# The goal of this project is to allow multiple different versions of 7DTD to run from the same server.
# 7dtd.sh will need to be modified for this purpose
# 7dtd.sh will also need to be made compatible to manage the undead legacy mod
#
#