#!/usr/bin/env bash # One-time setup for the LAN party's dedicated box: installs a Forge 1.20.1 # Minecraft server and wraps it in lazymc (auto-sleep when empty / auto-wake # on connect), as a systemd service so it runs unattended for the 3 days. # # File distribution (install.sh/install.ps1/modpack.zip) is NOT handled by # this script — see HOSTING.md, it's served from Gitea instead. # # Target: a Linux machine (Debian/Ubuntu/etc with systemd) at the venue. # Run as a normal user with sudo rights: ./setup-server.sh set -euo pipefail # ---- EDIT ME ---- FORGE_MC_VERSION="1.20.1" FORGE_BUILD="47.4.28" # current recommended build for 1.20.1 — check files.minecraftforge.net if this is stale MC_PUBLIC_PORT=25565 # what players connect to (lazymc listens here) MC_INTERNAL_PORT=25566 # real server listens here, lazymc proxies to it SLEEP_AFTER=300 # idle seconds before lazymc stops the real server (this lazymc build wants a plain integer, not "5m") MIN_RAM="2G" MAX_RAM="6G" # 5-8 players; see ../HOSTING.md sizing table — bump to 8G (9-12p) or 10-12G (13-15p) # ------------------ BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SERVER_DIR="$BASE_DIR/mcserver" FORGE_VERSION="${FORGE_MC_VERSION}-${FORGE_BUILD}" command -v java >/dev/null || { echo "Java not found. Install a Java 17+ JDK (e.g. 'sudo apt install -y openjdk-17-jre-headless') then re-run."; exit 1; } mkdir -p "$SERVER_DIR" # ---- 1. Install the Forge server ---- if [[ ! -f "$SERVER_DIR/run.sh" ]]; then echo "==> Downloading Forge $FORGE_VERSION installer" installer_url="https://maven.minecraftforge.net/net/minecraftforge/forge/${FORGE_VERSION}/forge-${FORGE_VERSION}-installer.jar" curl -fsSL -o "$SERVER_DIR/forge-installer.jar" "$installer_url" read -rp "Do you accept the Minecraft EULA (https://aka.ms/MinecraftEULA)? [y/N] " eula_ans [[ "$eula_ans" =~ ^[Yy]$ ]] || { echo "EULA not accepted, aborting."; exit 1; } echo "==> Running Forge server installer" (cd "$SERVER_DIR" && java -jar forge-installer.jar --installServer) echo "eula=true" > "$SERVER_DIR/eula.txt" else echo "==> Forge server already installed, skipping" fi # JVM heap flags go in user_jvm_args.txt, NOT on lazymc's command line — run.sh # forwards any args after "nogui" straight to Minecraft's own arg parser (not # the JVM), so passing -Xmx/-Xms there crashes with "X is not a recognized option". cat > "$SERVER_DIR/user_jvm_args.txt" </dev/null; then sed -i "s/^${key}=.*/${kv}/" "$SERVER_DIR/server.properties" else echo "$kv" >> "$SERVER_DIR/server.properties" fi done mkdir -p "$SERVER_DIR/mods" echo "==> NOTE: copy the same mod jars from your client modpack's mods/ folder into $SERVER_DIR/mods/ (Create, Flywheel, Farmer's Delight + addons, JEI, etc.) before first boot." # ---- 2. Install lazymc ---- # Pinned to v0.2.10, NOT "latest" — v0.2.11 has a confirmed, still-open upstream # regression where it never detects a Forge server as ready (timvisee/lazymc#65, # #86). 0.2.10 was the last version that correctly detects Forge startup. LAZYMC_VERSION="v0.2.10" if [[ ! -x "$BASE_DIR/lazymc" ]]; then echo "==> Downloading lazymc $LAZYMC_VERSION" curl -fsSL -o "$BASE_DIR/lazymc" "https://github.com/timvisee/lazymc/releases/download/${LAZYMC_VERSION}/lazymc-${LAZYMC_VERSION}-linux-x64" chmod +x "$BASE_DIR/lazymc" else echo "==> lazymc already present, skipping" fi cat > "$BASE_DIR/lazymc.toml" < Wrote lazymc.toml (sleeps after ${SLEEP_AFTER} empty, public port ${MC_PUBLIC_PORT} -> internal ${MC_INTERNAL_PORT})" # ---- 3. systemd services ---- sudo tee /etc/systemd/system/mc-lazymc.service >/dev/null < Done." echo " - Minecraft server: public port ${MC_PUBLIC_PORT}, sleeps after ${SLEEP_AFTER} idle, wakes on connect." echo " - Install scripts + modpack.zip are served from Gitea, not this box — see ../HOSTING.md." echo " - Copy your client mod jars into ${SERVER_DIR}/mods/ if you haven't yet, then: sudo systemctl restart mc-lazymc" if command -v ufw >/dev/null && sudo ufw status | grep -q "Status: active"; then echo "==> ufw is active — opening ${MC_PUBLIC_PORT}/tcp" sudo ufw allow "${MC_PUBLIC_PORT}/tcp" fi