197 lines
6.0 KiB
Bash
Executable File
197 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Single entry point for deploying from removable media.
|
|
#
|
|
# ./install.sh reads deploy.conf next to this script
|
|
# ./install.sh -c other.conf reads a different config
|
|
# ./install.sh --check verify prerequisites and exit
|
|
#
|
|
# Copies itself off read-only media, installs prerequisites, and runs the
|
|
# deploy. Everything is configured in deploy.conf, so there are no flags to
|
|
# remember at the console.
|
|
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
CONF="$HERE/deploy.conf"
|
|
CHECK_ONLY=0
|
|
WORKDIR=""
|
|
|
|
die() { printf '\n\033[1;31merror:\033[0m %s\n\n' "$*" >&2; exit 1; }
|
|
step() { printf '\n\033[1m=== %s ===\033[0m\n\n' "$*"; }
|
|
info() { echo ">>> $*"; }
|
|
warn() { echo " warning: $*" >&2; }
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-c|--config) CONF="${2:-}"; shift 2 ;;
|
|
--check) CHECK_ONLY=1; shift ;;
|
|
-w|--workdir) WORKDIR="${2:-}"; shift 2 ;;
|
|
-h|--help) awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "$0"; exit 0 ;;
|
|
*) die "unknown option: $1" ;;
|
|
esac
|
|
done
|
|
|
|
[ "$(id -u)" -ne 0 ] || die "run this as your normal user, not root — it calls sudo itself"
|
|
|
|
# ------------------------------------------------------------------ config ---
|
|
|
|
[ -f "$CONF" ] || die "no config at $CONF
|
|
Copy deploy.conf.example to deploy.conf and edit it first."
|
|
|
|
# shellcheck source=/dev/null
|
|
. "$CONF"
|
|
|
|
for v in PACK_NAME AUTHOR MIRROR_URL SHARE; do
|
|
[ -n "${!v:-}" ] || die "$v is not set in $CONF"
|
|
done
|
|
|
|
MC_VERSION="${MC_VERSION:-1.21.1}"
|
|
NEOFORGE="${NEOFORGE:-latest}"
|
|
MC_PORT="${MC_PORT:-25565}"
|
|
HTTP_PORT="${HTTP_PORT:-18080}"
|
|
HTTP_BIND="${HTTP_BIND:-0.0.0.0}"
|
|
XMX="${XMX:-10G}"
|
|
XMS="${XMS:-$XMX}"
|
|
ACCEPT_EULA="${ACCEPT_EULA:-no}"
|
|
START_SERVER="${START_SERVER:-no}"
|
|
CAP_ZFS_ARC="${CAP_ZFS_ARC:-}"
|
|
|
|
# ------------------------------------------------------------- prequisites ---
|
|
|
|
step "Checking prerequisites"
|
|
|
|
MISSING=()
|
|
need() { command -v "$1" >/dev/null || MISSING+=("$2"); }
|
|
need java java-21-openjdk-headless
|
|
need curl curl
|
|
need go golang
|
|
need python3 python3
|
|
need zfs zfs
|
|
need findmnt util-linux
|
|
need mkfifo coreutils
|
|
|
|
if [ "${#MISSING[@]}" -gt 0 ]; then
|
|
info "missing: ${MISSING[*]}"
|
|
if (( CHECK_ONLY )); then
|
|
die "prerequisites missing (see above)"
|
|
fi
|
|
info "installing with dnf"
|
|
sudo dnf install -y "${MISSING[@]}" \
|
|
|| die "could not install: ${MISSING[*]}
|
|
Install them by hand and re-run."
|
|
else
|
|
info "all present"
|
|
fi
|
|
|
|
jver="$(java -version 2>&1 | head -1 | grep -oE '"[0-9]+' | tr -d '"' || echo 0)"
|
|
[ "${jver:-0}" -ge 21 ] || warn "java is $jver; NeoForge for 1.21.x wants 21"
|
|
|
|
if ! mountpoint -q "$SHARE"; then
|
|
die "$SHARE is not a mountpoint — the ZFS dataset is not mounted.
|
|
Import and mount the pool first:
|
|
sudo zpool import -a && sudo zfs mount -a
|
|
Then re-run. Deploying onto an unmounted path would fill the root disk."
|
|
fi
|
|
info "$SHARE is mounted ($(findmnt -no SOURCE "$SHARE"))"
|
|
|
|
if (( CHECK_ONLY )); then
|
|
step "Prerequisites OK"
|
|
exit 0
|
|
fi
|
|
|
|
# --------------------------------------------------------------- workspace ---
|
|
|
|
# The media is very likely read-only, and the deploy needs somewhere writable
|
|
# for the go build and the pack. Copy the kit onto the host first.
|
|
if [ -z "$WORKDIR" ]; then
|
|
if [ -w "$HERE" ]; then
|
|
WORKDIR="$HERE"
|
|
else
|
|
WORKDIR="$HOME/mc-packwiz-deploy"
|
|
info "media is read-only — copying the kit to $WORKDIR"
|
|
mkdir -p "$WORKDIR"
|
|
cp -f "$HERE"/*.sh "$HERE"/*.py "$WORKDIR"/ 2>/dev/null || true
|
|
cp -f "$CONF" "$WORKDIR/deploy.conf"
|
|
chmod +x "$WORKDIR"/*.sh "$WORKDIR"/*.py 2>/dev/null || true
|
|
fi
|
|
fi
|
|
cd "$WORKDIR"
|
|
[ -x ./deploy.sh ] || die "deploy.sh not found in $WORKDIR"
|
|
|
|
# ----------------------------------------------------------------- zfs arc ---
|
|
|
|
if [ -n "$CAP_ZFS_ARC" ]; then
|
|
if [ ! -f /etc/modprobe.d/zfs.conf ] || ! grep -q zfs_arc_max /etc/modprobe.d/zfs.conf; then
|
|
step "Capping the ZFS ARC at $CAP_ZFS_ARC bytes"
|
|
echo "options zfs zfs_arc_max=$CAP_ZFS_ARC" | sudo tee /etc/modprobe.d/zfs.conf >/dev/null
|
|
warn "the ARC cap needs a reboot (and 'sudo dracut --force') to take effect"
|
|
else
|
|
info "ZFS ARC already capped in /etc/modprobe.d/zfs.conf"
|
|
fi
|
|
fi
|
|
|
|
# ------------------------------------------------------------------ deploy ---
|
|
|
|
EULA_FLAG=""
|
|
case "${ACCEPT_EULA,,}" in
|
|
yes|true|1) EULA_FLAG="--accept-eula" ;;
|
|
*) die "ACCEPT_EULA is not set to yes in $CONF.
|
|
Read https://aka.ms/MinecraftEULA, then set ACCEPT_EULA=\"yes\" to accept it." ;;
|
|
esac
|
|
|
|
step "Deploying $PACK_NAME"
|
|
|
|
./deploy.sh \
|
|
-n "$PACK_NAME" \
|
|
-a "$AUTHOR" \
|
|
-u "$MIRROR_URL" \
|
|
-m "$MC_VERSION" \
|
|
-N "$NEOFORGE" \
|
|
-s "$SHARE" \
|
|
-p "$MC_PORT" \
|
|
-H "$HTTP_PORT" \
|
|
-B "$HTTP_BIND" \
|
|
-X "$XMX" \
|
|
-x "$XMS" \
|
|
$EULA_FLAG
|
|
|
|
# ------------------------------------------------------------------- start ---
|
|
|
|
case "${START_SERVER,,}" in
|
|
yes|true|1)
|
|
step "Starting Minecraft"
|
|
sudo systemctl start minecraft
|
|
sleep 3
|
|
if systemctl is-active --quiet minecraft; then
|
|
info "minecraft.service is running"
|
|
else
|
|
warn "minecraft.service did not come up — journalctl -u minecraft -n 50"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# ------------------------------------------------------------------- done ----
|
|
|
|
SITE="${MIRROR_URL%/*}"
|
|
HOSTONLY="$(sed -e 's#^[a-z]*://##' -e 's#/.*##' -e 's#:.*##' <<<"$SITE")"
|
|
[ "$MC_PORT" = "25565" ] && SHOWN="$HOSTONLY" || SHOWN="$HOSTONLY:$MC_PORT"
|
|
|
|
step "Done"
|
|
cat <<EOF
|
|
Kit installed in: $WORKDIR
|
|
Pack HTTP server: ${HTTP_BIND}:${HTTP_PORT} (proxy / -> this)
|
|
Players connect to: $SHOWN
|
|
Setup guides: $SITE/setup-windows-packwiz.html
|
|
$SITE/setup-linux-packwiz.html
|
|
|
|
Still to do by hand:
|
|
1. Point your reverse proxy at ${HTTP_BIND}:${HTTP_PORT}
|
|
2. Drop mod jars into $SHARE/mods
|
|
3. Run $WORKDIR/mc-refresh-restart.sh to register them
|
|
|
|
sudo systemctl start minecraft
|
|
journalctl -u minecraft -f
|
|
echo "op YourName" | sudo tee /run/minecraft/console
|
|
EOF
|