#!/bin/bash echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nThis script should be run as root on a clean install of a Linux x64 system." echo "It should work by default on most Linux distributions, and is tested on Debian." echo "You can choose to do a full install, or update a server which was previously" echo "installed with the same script." echo -e "\nNOTICE: The Minecraft Fabric installer supports versions from 1.14 to latest." echo " For another Minecraft server version, download the desired server.jar" echo " file and move it to '/home/minecraft/server.jar'." echo "NOTICE: The available options for Java are: 8/16/17/21, for Linux x64." echo " For another Java version, download the desired build archive manually." echo " I recommend selecting a JRE release from Adoptium here:" echo " https://adoptium.net/temurin/releases/" echo " To install it, download and extract the archive to '/home/minecraft/'," echo " verify the Java binary can be found at '/home/minecraft/jdk*/bin/java'." while true; do echo "" read -p " Do you want to proceed? [Y/n] " proceed case $proceed in [yY]|"" ) break;; [nN] ) echo "=> Exiting."; exit;; * ) echo "=> Invalid response.";; esac done echo -e "\n=> Running compatibility checks..." echo -n "=> Checking curl... " curl --version &> /dev/null && echo "DONE" || chk1="failed" if [ "$chk1" == "failed" ]; then echo "FAIL"; fi echo -n "=> Checking systemd... " systemd-notify --booted && echo "DONE" || chk2="failed" if [ "$chk2" == "failed" ]; then echo "FAIL"; fi echo -n "=> Checking root privileges... " if [ "$EUID" == 0 ]; then echo "DONE"; else chk3="failed"; echo "FAIL"; fi echo -n "=> Checking /etc/systemd/system/ permissions... " touch /etc/systemd/system/permission.test &> /dev/null && rm /etc/systemd/system/permission.test &> /dev/null && echo "DONE" || chk4="failed" if [ "$chk4" == "failed" ]; then echo "FAIL"; fi echo -n "=> Checking internet connection... " ping -c 1 8.8.8.8 &> /dev/null && echo "DONE" || chk5="failed" if [ "$chk5" == "failed" ]; then echo "FAIL"; fi echo -n "=> Checking DNS resolution... " ping -c 1 google.com &> /dev/null && echo "DONE" || chk6="failed" if [ "$chk6" == "failed" ]; then echo "FAIL"; fi if [ "$chk1" == "failed" ]; then echo "WARNING: curl command error, downloads will fail."; fi if [ "$chk2" == "failed" ]; then echo "WARNING: this system is not using systemd, please skip creating unit files."; fi if [ "$chk3" == "failed" ]; then echo "WARNING: root privileges are not detected, creating a user will fail."; fi if [ "$chk4" == "failed" ]; then echo "WARNING: cannot write to systemd directory, please skip creating unit files."; fi if [ "$chk5" == "failed" ]; then echo "WARNING: cannot connect to the internet, downloads will fail."; fi if [ "$chk6" == "failed" ]; then echo "WARNING: cannot resolve domain names, downloads will fail."; fi if [[ "$chk1"&&"$chk2"&&"$chk3"&&"$chk4"&&"$chk5" != "failed" ]]; then echo -e "All checks complete.\n"; fi if [[ "$chk1"||"$chk2"||"$chk3"||"$chk4"||"$chk5" == "failed" ]]; then while true; do echo "" read -p " At least one check failed, are you sure you want to proceed? [y/N] " skipwarn case $skipwarn in [yY] ) echo "=> Ignoring warnings..."; break;; [nN]|"" ) echo "=> Exiting."; exit;; * ) echo "=> Invalid response.";; esac done fi echo -e "\nChoose to install a new server or update an existing one." echo "WARNING: Only update an existing server if it was initially installed using this" echo " script, or if you know that it's been set up in the same way." echo "NOTICE: This will replace any existing /home/minecraft-old/ directory." while true; do echo "" read -p " Update an existing server? [y/N] " update case $update in [yY] ) update="true"; echo "=> Updating..."; break;; [nN]|"" ) echo "=> Skipping..."; break;; * ) echo "=> Invalid response.";; esac done if [ "$update" == "true" ]; then echo -n "=> Removing previous minecraft-old directory... " rm -rf /home/minecraft-old/ && echo "DONE" echo -n "=> Backing up current minecraft home directory... " mv /home/minecraft/ /home/minecraft-old/ && echo "DONE" echo -n "=> Creating new minecraft home directory... " mkdir -p /home/minecraft && echo "DONE" echo -n "=> Copying world... " cp -R /home/minecraft-old/world/ /home/minecraft/world/ && echo "DONE" echo -n "=> Copying mods... " cp -R /home/minecraft-old/mods/ /home/minecraft/mods/ && echo "DONE" echo -n "=> Copying config... " cp -R /home/minecraft-old/config/ /home/minecraft/config/ && echo "DONE" echo -n "=> Copying defaultconfigs... " cp -R /home/minecraft-old/defaultconfigs/ /home/minecraft/defaultconfigs/ && echo "DONE" echo -n "=> Copying properties and player lists... " cp /home/minecraft-old/banned-ips.json /home/minecraft-old/banned-players.json /home/minecraft-old/ops.json /home/minecraft-old/server.properties /home/minecraft-old/whitelist.json /home/minecraft/ && echo "DONE" echo "=> Finished copying data." echo "NOTICE: After completing the installation, please check for other config files" echo " that you may want to keep such as mod-specific folders, logs, etcetera." echo "NOTICE: Mods must be updated manually, please do so before starting the server." else echo -e "\n=> Creating 'minecraft' user..." mkdir -p /home/minecraft useradd -d /home/minecraft/ minecraft &> /dev/null && ( echo " Please set a password for the user:"; passwd minecraft ) fi cd /home/minecraft/ echo -e "\nChoose a valid version of Java." echo "Minecraft requires Java 8 for 1.16.5 and earlier, Java 16 for 1.17-1.17.1," echo "Java 17 for 1.18-1.20.4, and Java 21 for 1.20.5 and later." while true; do echo "" read -p " Enter version [8,16,17,21] (press ENTER to skip): " java case $java in 16 ) echo "=> Downloading Java $java (Adoptium Eclipse Temurin)..." API_URL="https://api.adoptium.net/v3/binary/latest/$java/ga/linux/x64/jdk/hotspot/normal/eclipse" FETCH_URL=$(curl -s -w %{redirect_url} "${API_URL}") curl -o "jdk-$java.tar.gz" -Ls "${FETCH_URL}" tar -xf jdk-$java.tar.gz rm jdk-$java.tar.gz echo "=> Downloaded Java $java." break;; 8|17|21 ) echo "=> Downloading Java $java (Adoptium Eclipse Temurin)..." API_URL="https://api.adoptium.net/v3/binary/latest/$java/ga/linux/x64/jre/hotspot/normal/eclipse" FETCH_URL=$(curl -s -w %{redirect_url} "${API_URL}") curl -o "jdk-$java-jre.tar.gz" -Ls "${FETCH_URL}" tar -xf jdk-$java-jre.tar.gz rm jdk-$java-jre.tar.gz echo "=> Downloaded Java $java." break;; "" ) echo "=> Skipping installation..."; break;; * ) echo "=> Invalid response.";; esac done echo -e "\nChoose if you want to use the Fabric server installer." echo "The Fabric installer supports Minecraft 1.14 to latest." echo "Skip if you have a server.jar, make sure it's at '/home/minecraft/server.jar'." while true; do echo "" read -p " Use Fabric server installer? [Y/n] " fabric case $fabric in [yY]|"" ) fabric="install"; break;; [nN] ) echo "=> Skipping Fabric installer..."; break;; * ) echo "=> Invalid response.";; esac done if [ "$fabric" == "install" ]; then serverjar="fabric-server-launch.jar" echo "=> Downloading Fabric installer..." curl -s -o 'fabric-installer.jar' https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar while true; do echo "" read -p " Select valid Minecraft version to install (press ENTER for latest): " mc case $mc in "" ) echo "=> Installing latest Fabric server..." /home/minecraft/jdk*/bin/java -jar fabric-installer.jar server -downloadMinecraft && break;; * ) echo "=> Installing $mc Fabric server..." /home/minecraft/jdk*/bin/java -jar fabric-installer.jar server -mcversion $mc -downloadMinecraft && break || echo "=> Invalid version.";; esac done echo "=> Running server once to generate files..." /home/minecraft/jdk*/bin/java -jar fabric-server-launch.jar echo "=> Server files created." echo "=> Installed $mc Fabric server." else serverjar="server.jar" while true; do echo "" read -p " Is the server.jar available at '/home/minecraft/server.jar'? [Y/n] " mc case $mc in [yY]|"" ) echo "=> Installing server..." /home/minecraft/jdk*/bin/java -jar server.jar;; [nN] ) echo "=> Can't install, exiting."; exit;; * ) echo "=> Invalid response.";; esac done fi while true; do echo "" read -p " Agree to the EULA? [Y/n] " eula case $eula in [yY]|"" ) sed -i '3s/.*/eula=true/' eula.txt && echo "=> EULA set to true."; break;; [nN] ) echo "=> Skipping..."; break;; * ) echo "=> Invalid response.";; esac done echo "=> Creating run script with Java arguments..." touch /home/minecraft/run.sh chmod +x /home/minecraft/run.sh echo -e "\nChoose allocated server memory in GB" echo "You should leave roughly 2GB available for the host/OS, e.g. use up to 6GB if" echo "the system has 8GB. I recommend using 2-6 for best performance, and avoiding >8" echo "unless there are many players." while true; do echo "" read -p " Enter allocated memory [1-16] (press ENTER to use 4GB): " mem case $mem in [1-9]|1[0-6] ) echo "=> Allocating ${mem}GB"...; break;; "" ) echo "=> Allocating 4GB..."; mem="4"; break;; * ) echo "=> Invalid response.";; esac done cat > /home/minecraft/run.sh << EOF /home/minecraft/jdk*/bin/java -Xmx${mem}G -Xms${mem}G -XX:+UseG1GC -Dsun.rmi.dgc.server.gcInterval=2147483646 -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -jar $serverjar nogui EOF echo "=> Created run script in home directory." if [ "$update" != "true" ]; then echo -e "\nThis step allows you to set up autostart by creating systemd unit files." echo "This would allow you to start/stop the server with systemctl, view logs with" echo "journalctl, and send commands to Minecraft's console in the background." while true; do echo "" read -p " Do you want to set up autostart? [Y/n] " sysd case $sysd in [yY]|"" ) sysd="install"; break;; [nN] ) sysd="skip"; echo "=> Skipping..."; break;; * ) echo "=> Invalid response.";; esac done fi if [ "$sysd" == "install" ]; then echo "=> Creating systemd unit files..." cat > /etc/systemd/system/minecraft.service << EOF [Unit] Description=A dedicated Minecraft server After=network.target [Service] User=minecraft Type=simple KillSignal=SIGCONT Sockets=minecraft.socket WorkingDirectory=/home/minecraft/ ExecStart=/bin/sh -c "/home/minecraft/run.sh < /run/minecraft.control" ExecStop=/bin/sh -c "echo '/stop' > /run/minecraft.control" Type=exec Restart=on-failure [Install] WantedBy=multi-user.target EOF cat > /etc/systemd/system/minecraft.socket << EOF [Unit] BindsTo=minecraft.service [Socket] ListenFIFO=/run/minecraft.control FileDescriptorName=control RemoveOnStop=true SocketMode=0660 SocketUser=minecraft EOF echo "=> Created systemd unit files." systemctl enable minecraft.service &> /dev/null echo "=> Enabled systemd service." echo "=> The server is set up to autostart and restart automatically." cat > /home/minecraft/console.sh << EOF echo "$*" > /run/minecraft.control EOF chmod +x /home/minecraft/console.sh echo "=> Created executable console script in home directory." fi chown -R minecraft /home/minecraft echo "=> User 'minecraft' now owns all files in home directory." echo -e "\nInstallation complete, server is not running." echo "NOTICE: Please configure server.properties before starting the server." if [ "$fabric" == "install" ]; then echo "NOTICE: It's recommended to download performance mods such as Lithium," echo " FerriteCore, and ModernFix." fi if [ "$sysd" == "skip" ]; then echo -e "\nStart the server with the run script, or set up a user crontab for autostart." echo " $ ./run.sh" fi if [ "$sysd" == "install" ]; then echo -e "\nSystemd is in use, the server will automatically start on boot." echo "NOTICE: The server can be stopped by using either systemd, the /stop command," echo " or shutting down the host. Each method performs a clean shutdown, so the" echo " server won't lose data. You may notice a delay shutting down the host as" echo " the Minecraft server stops." echo -e "\nMany commands are available with systemd, some important ones are:" echo "Executing commands in the Minecraft server console using a script:" echo " $ ./console.sh '/'" echo "View server messages with journalctl: (Shift+G jumps to the end)" echo " # journalctl -u minecraft" echo "Or follow them as they update with:" echo " # journalctl -f -u minecraft" echo "And easily perform a clean start/stop of the server with:" echo " # systemctl {start,stop} minecraft" fi