Add Reaper's Sky dedicated server deploy files
- server/mods.json: 59 server-safe mods pinned by sha1 (19 client-only excluded) - server/deploy.sh: idempotent Debian 13 installer (Java 21, NeoForge 21.1.248, mods, eula/server.properties, 8G run.sh) - server/build_mods.py: regenerate mods.json from the Prism instance - server/README.md: setup + ops guide
This commit is contained in:
Executable
+147
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Reaper's Sky - dedicated server deploy script (Debian 13 / trixie)
|
||||
#
|
||||
# Installs everything needed to run the Reaper's Sky NeoForge 21.1.248 server:
|
||||
# - OpenJDK 21 (JRE, headless) + curl/unzip
|
||||
# - NeoForge 21.1.248 server via its official installer
|
||||
# - the 59 server-safe mods (pinned in mods.json, verified by sha1)
|
||||
# - eula.txt + server.properties (IP reaperofveriod.nl)
|
||||
# - run.sh (8 GB, G1GC)
|
||||
#
|
||||
# Usage: sudo ./deploy.sh (installs packages, needs root/sudo)
|
||||
# ./deploy.sh (idempotent; safe to re-run)
|
||||
#
|
||||
# Defaults:
|
||||
# DIR = "$HOME/reaper-sky-server"
|
||||
# MEMORY = 8G
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
NEOFORGE_VERSION="21.1.248"
|
||||
MC_VERSION="1.21.1"
|
||||
INSTALLER_URL="https://maven.neoforged.net/releases/net/neoforged/neoforge/${NEOFORGE_VERSION}/neoforge-${NEOFORGE_VERSION}-installer.jar"
|
||||
|
||||
# --- config (override via env if you want) ------------------------------------
|
||||
SERVER_DIR="${DIR:-$HOME/reaper-sky-server}"
|
||||
MEMORY="${MEMORY:-8G}"
|
||||
SERVER_IP="${SERVER_IP:-reaperofveriod.nl}"
|
||||
DEFAULT_MOTD="Reaper's Sky"
|
||||
MOTD="${MOTD:-$DEFAULT_MOTD}"
|
||||
MAX_PLAYERS="${MAX_PLAYERS:-10}"
|
||||
|
||||
log() { printf '\033[1;34m[deploy]\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[1;31m[deploy] ERROR:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# --- 1. system packages (Debian 13 ships OpenJDK 21) --------------------------
|
||||
install_packages() {
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
if command -v sudo >/dev/null 2>&1; then SUDO="sudo"; else SUDO=""; fi
|
||||
else
|
||||
SUDO=""
|
||||
fi
|
||||
if command -v java >/dev/null 2>&1; then
|
||||
log "Java already present: $(java -version 2>&1 | head -1)"
|
||||
else
|
||||
log "Installing openjdk-21-jre-headless, curl, unzip (apt)..."
|
||||
${SUDO:+sudo} apt-get update -qq
|
||||
${SUDO:+sudo} apt-get install -y -qq openjdk-21-jre-headless curl unzip
|
||||
fi
|
||||
java -version >/dev/null 2>&1 || die "Java 21 not available after install"
|
||||
}
|
||||
|
||||
# --- 2. NeoForge server --------------------------------------------------------
|
||||
install_neoforge() {
|
||||
mkdir -p "$SERVER_DIR"
|
||||
cd "$SERVER_DIR"
|
||||
if [ -f "run.sh" ] && [ -d "libraries/net/neoforged/neoforge/$NEOFORGE_VERSION" ]; then
|
||||
log "NeoForge $NEOFORGE_VERSION already installed."
|
||||
return
|
||||
fi
|
||||
log "Downloading NeoForge $NEOFORGE_VERSION installer..."
|
||||
curl -fL --retry 3 -o "neoforge-${NEOFORGE_VERSION}-installer.jar" "$INSTALLER_URL"
|
||||
log "Running installer --installServer ..."
|
||||
java -jar "neoforge-${NEOFORGE_VERSION}-installer.jar" --installServer
|
||||
rm -f "neoforge-${NEOFORGE_VERSION}-installer.jar"
|
||||
chmod +x run.sh
|
||||
}
|
||||
|
||||
# --- 3. server mods (verified by sha1) -----------------------------------------
|
||||
install_mods() {
|
||||
[ -f "$SCRIPT_DIR/mods.json" ] || die "mods.json not found next to deploy.sh"
|
||||
mkdir -p "$SERVER_DIR/mods"
|
||||
cd "$SERVER_DIR/mods"
|
||||
python3 - "$SCRIPT_DIR/mods.json" <<'PY'
|
||||
import json, sys, hashlib, subprocess, os
|
||||
manifest = json.load(open(sys.argv[1]))
|
||||
for m in manifest["mods"]:
|
||||
fname, url, want = m["file"], m["url"], m["sha1"]
|
||||
tmp = fname + ".part"
|
||||
if os.path.exists(fname):
|
||||
h = hashlib.sha1()
|
||||
with open(fname, "rb") as fh:
|
||||
for b in iter(lambda: fh.read(65536), b""):
|
||||
h.update(b)
|
||||
if h.hexdigest() == want:
|
||||
continue # already present & correct
|
||||
subprocess.run(["curl", "-fL", "--retry", "3", "-o", tmp, url], check=True)
|
||||
h = hashlib.sha1()
|
||||
with open(tmp, "rb") as fh:
|
||||
for b in iter(lambda: fh.read(65536), b""):
|
||||
h.update(b)
|
||||
if h.hexdigest() != want:
|
||||
os.unlink(tmp)
|
||||
raise SystemExit(f"sha1 mismatch for {fname}")
|
||||
os.rename(tmp, fname)
|
||||
print(f" + {fname}")
|
||||
PY
|
||||
log "Mods ready: $(ls -1 "$SERVER_DIR/mods"/*.jar | wc -l) jars installed."
|
||||
}
|
||||
|
||||
# --- 4. eula + server.properties -----------------------------------------------
|
||||
write_config() {
|
||||
cd "$SERVER_DIR"
|
||||
if [ ! -f eula.txt ]; then
|
||||
printf 'eula=true\n' > eula.txt
|
||||
log "Accepted Minecraft EULA (eula.txt)."
|
||||
fi
|
||||
cat > server.properties <<EOF
|
||||
# Generated by Reaper's Sky deploy.sh
|
||||
server-ip=$SERVER_IP
|
||||
server-port=25565
|
||||
motd=$MOTD
|
||||
max-players=$MAX_PLAYERS
|
||||
online-mode=true
|
||||
difficulty=hard
|
||||
level-type=default
|
||||
allow-nether=true
|
||||
spawn-protection=0
|
||||
view-distance=10
|
||||
simulation-distance=10
|
||||
EOF
|
||||
log "Wrote server.properties (IP=$SERVER_IP, max=$MAX_PLAYERS)."
|
||||
}
|
||||
|
||||
# --- 5. run script ---------------------------------------------------------------
|
||||
write_run() {
|
||||
cat > "$SERVER_DIR/run.sh" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
cd "$(dirname "$(readlink -f "$0")")"
|
||||
exec java -XmsMEMORY -XmxMEMORY -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 \
|
||||
@libraries/net/neoforged/neoforge/NEOFORGE_VERSION/unix_args.txt nogui
|
||||
EOF
|
||||
sed -i "s/MEMORY/$MEMORY/g; s/NEOFORGE_VERSION/$NEOFORGE_VERSION/g" "$SERVER_DIR/run.sh"
|
||||
chmod +x "$SERVER_DIR/run.sh"
|
||||
log "Wrote run.sh ($MEMORY RAM). Start with: cd $SERVER_DIR && ./run.sh"
|
||||
}
|
||||
|
||||
install_packages
|
||||
install_neoforge
|
||||
install_mods
|
||||
write_config
|
||||
write_run
|
||||
|
||||
log "Done. Reaper's Sky server is at: $SERVER_DIR"
|
||||
log "First boot generates the world. Run it with: cd $SERVER_DIR && ./run.sh"
|
||||
log "Console: run inside tmux/screen so it keeps running when you disconnect."
|
||||
log "To stop later: use the server console command stop"
|
||||
Reference in New Issue
Block a user