Minecraft Fabric Server Deployments with Bash
Automating Minecraft Fabric Server Deployments with Bash
In the world of Minecraft, setting up a dedicated server provides a persistent world for players to collaborate and build. While rewarding, the manual installation and configuration process is repetitive and prone to error. This article introduces a Bash script designed to automate the deployment of a Minecraft server using the Fabric mod loader on Ubuntu server.
Purpose
The primary purpose of this script is to provide a reliable, repeatable, and automated method for deploying a Minecraft Fabric server. It addresses the common challenges of manual setup, which include installing the correct Java version, configuring the server properties, setting up a dedicated user, and ensuring the server runs as a managed service. By encapsulating these steps into a single, rerunnable script, it saves significant time and ensures a consistent configuration across multiple deployments. The need for such automation is underscored by the vast and active Minecraft community, with millions of players who benefit from stable, privately-hosted environments.
This script is based on my Minecraft Server script located here: https://craigwilson.blog/post/2025/2025-06-21-minecraftserver/
TL;DR: Here’s a bash script to fully automate the setup of a Minecraft Fabric Server Setup Script on Ubuntu: https://gist.github.com/CraigWilsonOZ/22bf4bc9a48e75970bbebc2de95f1dea
Use Cases
This automation script adds value in several practical scenarios:
- Personal Server Hosting: Quickly deploy a server for friends and family without needing to manually work through the setup process.
- Mod Development and Testing: Developers can create clean, identical server environments on-demand to test the functionality and compatibility of their Fabric mods.
- Compliance and Standardisation: System administrators in educational or club settings can enforce a standard server configuration, ensuring all deployed instances meet specific operational and security guidelines.
- Incident Response: In the event of a server failure or corruption, the script facilitates a rapid redeployment of a known-good server state, minimising downtime.
Prerequisites
To ensure successful execution, the following requirements must be met:
- Operating System: A Debian-based Linux distribution (e.g., Debian, Ubuntu, Linux Mint).
- Permissions: Root or
sudo
privileges are required to install software and create users and services. - Software: The script will automatically install the following dependencies if they are not present:
openjdk-21-jre-headless
git
build-essential
cron
wget
- Network Access: An active internet connection is necessary to download the Java Development Kit (JDK), the Fabric installer, and the
mcrcon
utility.
How the Topic Works
The script follows a logical, idempotent workflow, meaning it can be run multiple times without causing issues; it checks the system state at each step and only performs actions that are necessary.
- Initial Checks: The script first verifies it is running with root privileges.
- Dependency Installation: It updates the package manager and installs the required software dependencies.
- User and Directory Setup: A dedicated, unprivileged user (
mcfabric
) is created to run the server, enhancing security. It then creates the necessary directory structure (/opt/mcfabric
) and sets the correct ownership. - EULA Acceptance: The Minecraft End User License Agreement (EULA) is automatically accepted by creating the
eula.txt
file. - Fabric Server Installation: The script checks if the Fabric server JAR already exists. If not, it downloads the specified version of the Fabric installer, runs it to download the server files, and then cleans up the installer.
- Configuration: A
server.properties
file is generated with pre-defined settings, including a randomly generated RCON (Remote Console) password for secure administration. - MCRCON Installation: It clones the
mcrcon
GitHub repository and compiles the utility, which allows for command-line administration of the running server. - Helper Scripts: Several helper scripts are created in the tools directory for starting the server, connecting via
mcrcon
, and performing backups. - Systemd Service: A
systemd
service file is created to manage the Minecraft server, allowing it to start automatically on boot and be managed with standardsystemctl
commands. - Backup Cron Job: A cron job is established to run a daily backup script, which archives the server world and configuration.
- Service Activation: Finally, the
systemd
daemon is reloaded, and the Minecraft service is enabled and started.
The Script
The complete script is provided below. Save it as setup-fabric.sh
and make it executable using chmod +x setup-fabric.sh
.
#!/bin/bash
#==============================================================================
# Minecraft Fabric Server Setup Script
#
# Author: Craig Wilson
# Version: 2.1 (Fabric Edition)
# Last Modified: 2025-07-05
#
# Description:
# This script automates the setup of a Minecraft Fabric server on a
# Debian-based system. It is designed to be rerunnable; it will check the
# system state and only perform actions that are necessary.
#
#==============================================================================
# --- Script Configuration and Preamble ---
# Exit immediately if a command exits with a non-zero status.
set -euo pipefail
# Set DEBIAN_FRONTEND to noninteractive to prevent prompts.
export DEBIAN_FRONTEND=noninteractive
# --- Function Definitions ---
#
# Performs initial checks to ensure script can run successfully.
#
initial_checks() {
echo "▶ Performing initial checks..."
# Check for root privileges
if [ "$EUID" -ne 0 ]; then
echo "ERROR: Please run this script as root or using sudo." >&2
exit 1
fi
}
#
# Displays the help message for the script.
#
display_help() {
cat << EOF
Minecraft Fabric Server Setup Script - v2.1
This script automates the setup of a Minecraft Fabric server on a Debian-based system.
It is rerunnable and will skip steps that are already completed.
Usage:
sudo ./setup-fabric.sh
Options:
-h, --help Display this help message and exit.
The script must be run with root (sudo) privileges. All server configuration
can be adjusted in the '== Configuration ==' section of the script file.
EOF
}
# === Configuration ===
MINECRAFT_USER="mcfabric"
INSTALL_DIR="/opt/mcfabric"
SERVER_DIR="$INSTALL_DIR/server"
TOOLS_DIR="$INSTALL_DIR/tools"
LOGS="$INSTALL_DIR/logs"
BACKUP_DIR="$INSTALL_DIR/backup"
MCRCON_DIR="$TOOLS_DIR/mcrcon"
# --- Fabric & Minecraft Configuration ---
# These three versions are linked. Get compatible versions from https://fabricmc.net/use/server/
MINECRAFT_VERSION="1.21.7"
FABRIC_LOADER_VERSION="0.16.14"
FABRIC_INSTALLER_VERSION="1.1.0"
# This URL is now built from the versions above using the official Fabric Meta API.
FABRIC_INSTALLER_URL="https://meta.fabricmc.net/v2/versions/loader/${MINECRAFT_VERSION}/${FABRIC_LOADER_VERSION}/${FABRIC_INSTALLER_VERSION}/server/jar"
FABRIC_INSTALLER_JAR="fabric-installer.jar"
FABRIC_SERVER_JAR="fabric-server-launch.jar"
# --- General Server Configuration ---
PASSWORD=$(date +%s | sha256sum | base64 | head -c 32 ; echo)
MAX_MEMORY="8192M"
MIN_MEMORY="8192M"
MINECRAFT_PORT="25565"
RCON_PORT="25575"
MAX_PLAYERS="20"
JDK_VERSION="openjdk-21-jre-headless"
# --- Script Execution ---
# Parse command-line options for help flag
if [[ "${1-}" =~ ^(-h|--help)$ ]]; then
display_help
exit 0
fi
# Call the initial checks function.
initial_checks
echo "[+] Starting Minecraft Fabric Server Setup for user '$MINECRAFT_USER'"
# === Install Dependencies ===
echo "▶ Installing dependencies..."
sudo apt-get update
sudo apt-get install -y $JDK_VERSION git build-essential cron wget
# === Create User and Directories ===
echo "▶ Ensuring user and directories exist..."
sudo useradd -r -m -U -d "$INSTALL_DIR" -s /bin/bash "$MINECRAFT_USER" || echo "✔ User '$MINECRAFT_USER' already exists."
sudo mkdir -p "$SERVER_DIR" "$TOOLS_DIR" "$BACKUP_DIR"
# Create a symbolic link for the logs
if [ -d "$LOGS" ] && [ ! -L "$LOGS" ]; then
sudo rmdir "$LOGS"
fi
if [ ! -e "$LOGS" ]; then
echo "▶ Linking server logs directory..."
sudo -u "$MINECRAFT_USER" ln -s "$SERVER_DIR/logs" "$LOGS"
fi
sudo chown -R "$MINECRAFT_USER":"$MINECRAFT_USER" "$INSTALL_DIR"
sudo chown -h "$MINECRAFT_USER":"$MINECRAFT_USER" "$LOGS"
# === Accept EULA ===
echo "▶ Ensuring EULA is accepted..."
sudo -u "$MINECRAFT_USER" tee "$SERVER_DIR/eula.txt" > /dev/null <<EOF
eula=true
EOF
# === Install Fabric Server ===
if [ ! -f "$SERVER_DIR/$FABRIC_SERVER_JAR" ]; then
echo "▶ Fabric server not found. Starting installation..."
echo "▶ Downloading Fabric Installer for Minecraft $MINECRAFT_VERSION..."
sudo -u "$MINECRAFT_USER" wget --content-disposition -O "$SERVER_DIR/$FABRIC_INSTALLER_JAR" "$FABRIC_INSTALLER_URL"
echo "▶ Running Fabric installer..."
sudo -u "$MINECRAFT_USER" -H bash -c "cd '$SERVER_DIR' && /usr/bin/java -jar '$FABRIC_INSTALLER_JAR' server -mcversion '$MINECRAFT_VERSION' -loader '$FABRIC_LOADER_VERSION' -downloadMinecraft"
else
echo "✔ Fabric server JAR already exists. Skipping installation."
fi
# === Create Server Properties ===
echo "▶ Creating/updating server.properties..."
sudo -u "$MINECRAFT_USER" tee "$SERVER_DIR/server.properties" > /dev/null <<EOF
#Minecraft server properties
accepts-transfers=false
allow-flight=false
allow-nether=true
broadcast-console-to-ops=true
broadcast-rcon-to-ops=true
bug-report-link=
difficulty=easy
enable-command-block=false
enable-jmx-monitoring=false
enable-query=false
enable-rcon=true
enable-status=true
enforce-secure-profile=true
enforce-whitelist=false
entity-broadcast-range-percentage=100
force-gamemode=false
function-permission-level=2
gamemode=survival
generate-structures=true
generator-settings={}
hardcore=false
hide-online-players=false
initial-disabled-packs=
initial-enabled-packs=vanilla
level-name=world
level-seed=
level-type=minecraft\:normal
log-ips=true
max-chained-neighbor-updates=1000000
max-players=$MAX_PLAYERS
max-tick-time=60000
max-world-size=29999984
motd=A Minecraft Server
network-compression-threshold=256
online-mode=true
op-permission-level=4
pause-when-empty-seconds=60
player-idle-timeout=0
prevent-proxy-connections=false
pvp=true
query.port=$MINECRAFT_PORT
rate-limit=0
rcon.password=$PASSWORD
rcon.port=$RCON_PORT
region-file-compression=deflate
require-resource-pack=false
resource-pack=
resource-pack-id=
resource-pack-prompt=
resource-pack-sha1=
server-ip=
server-port=$MINECRAFT_PORT
simulation-distance=10
spawn-monsters=true
spawn-protection=16
sync-chunk-writes=true
text-filtering-config=
text-filtering-version=0
use-native-transport=true
view-distance=10
white-list=false
EOF
# === Install and Build MCRCON ===
if [ ! -d "$MCRCON_DIR" ]; then
echo "▶ Cloning and building mcrcon..."
sudo -u "$MINECRAFT_USER" git clone https://github.com/Tiiffi/mcrcon.git "$MCRCON_DIR"
sudo -u "$MINECRAFT_USER" bash -c "cd '$MCRCON_DIR' && gcc -std=gnu11 -pedantic -Wall -Wextra -O2 -s -o mcrcon mcrcon.c"
else
echo "✔ mcrcon directory already exists. Skipping clone and build."
fi
# === Create Helper Scripts ===
echo "▶ Creating/updating helper scripts..."
sudo -u "$MINECRAFT_USER" tee "$TOOLS_DIR/connect-mcrcon.sh" > /dev/null <<EOF
#!/bin/bash
$MCRCON_DIR/mcrcon -H 127.0.0.1 -P $RCON_PORT -p "$PASSWORD" -t
EOF
sudo -u "$MINECRAFT_USER" tee "$TOOLS_DIR/backup-minecraft.sh" > /dev/null <<EOF
#!/bin/bash
function rcon {
"$MCRCON_DIR/mcrcon" -H 127.0.0.1 -P $RCON_PORT -p "$PASSWORD" "\$1"
}
echo "Running Minecraft backup..."
rcon "save-off"; rcon "save-all"; sleep 10
tar -cvpzf "$BACKUP_DIR/server-\$(date +%F-%H-%M).tar.gz" "$SERVER_DIR"
rcon "save-on"
echo "Backup complete."
find "$BACKUP_DIR" -type f -mtime +31 -name '*.gz' -delete
EOF
sudo -u "$MINECRAFT_USER" tee "$TOOLS_DIR/start-minecraft.sh" > /dev/null <<EOF
#!/bin/bash
cd "$SERVER_DIR" || exit
/usr/bin/java -Xmx$MAX_MEMORY -Xms$MIN_MEMORY -jar "$FABRIC_INSTALLER_JAR" nogui
EOF
# Make all shell scripts executable
sudo chmod +x $TOOLS_DIR/*.sh
# === Create Backup Cron Job ===
CRON_JOB="0 3 * * * $TOOLS_DIR/backup-minecraft.sh >> $LOGS/backup.log 2>&1"
if ! (sudo -u "$MINECRAFT_USER" crontab -l 2>/dev/null || true) | grep -Fq "$CRON_JOB"; then
echo "▶ Creating daily backup cron job..."
(sudo -u "$MINECRAFT_USER" crontab -l 2>/dev/null || true; echo "$CRON_JOB") | sudo -u "$MINECRAFT_USER" crontab -
else
echo "✔ Backup cron job already exists. Skipping."
fi
# === Create Systemd Service ===
echo "▶ Creating/updating systemd service file..."
sudo tee /etc/systemd/system/$MINECRAFT_USER.service > /dev/null <<EOF
[Unit]
Description=Minecraft Fabric Server
After=network.target
[Service]
User=$MINECRAFT_USER
WorkingDirectory=$SERVER_DIR
ExecStart=/usr/bin/java -Xmx$MAX_MEMORY -Xms$MIN_MEMORY -jar "$SERVER_DIR/$FABRIC_INSTALLER_JAR" nogui
ExecStop=$MCRCON_DIR/mcrcon -H 127.0.0.1 -P $RCON_PORT -p $PASSWORD stop
Restart=on-failure
SuccessExitStatus=0 1
[Install]
WantedBy=multi-user.target
EOF
# === Enable and Start Service (Safely) ===
sudo systemctl daemon-reload
if ! sudo systemctl is-active --quiet $MINECRAFT_USER; then
echo "▶ Starting and enabling the minecraft service..."
sudo systemctl enable --now $MINECRAFT_USER
else
echo "✔ Minecraft service is already active. Ensuring it is enabled on boot."
sudo systemctl enable $MINECRAFT_USER
echo "[!] The service definition or server properties may have changed. Run 'sudo systemctl restart $MINECRAFT_USER' to apply all changes."
fi
echo ""
echo "[+] Setup Complete. Your Fabric server is running under user '$MINECRAFT_USER'."
echo "[+] To add mods, place your .jar files in: $SERVER_DIR/mods"
echo "[*] To connect to the server console, run: $TOOLS_DIR/connect-mcrcon.sh"
echo "[*] Your RCON password is: $PASSWORD"
Security Considerations
- Privileged Operations: The script requires root access (
sudo
) to perform system-level changes. It is critical to review the script’s contents before execution to understand the commands being run. - Dedicated User: The server process runs under an unprivileged user (
mcfabric
). This is a security best practice that contains the potential impact of any vulnerability in the Minecraft server or its mods, preventing it from affecting the entire system. - Sensitive Data: The script automatically generates a strong, random password for RCON access. This password is saved in the
systemd
service file and helper scripts. Access to these files should be restricted. The final output displays this password; ensure it is stored securely if needed for external tools.
Limitations
- Platform Specificity: This script is designed exclusively for Debian-based Linux distributions due to its use of the
apt-get
package manager andsystemd
. It will not function on other operating systems like CentOS, Fedora, or Windows without significant modification. - Firewall Configuration: The script does not automatically configure firewall rules. To allow players to connect from the internet, you must manually open the configured Minecraft port (
25565
by default) in your system’s firewall (e.g.,ufw
,firewalld
). - Mod Management: The script sets up the Fabric server but does not install any mods. Mods (
.jar
files) must be manually downloaded and placed in the/opt/mcfabric/server/mods
directory.
Future Work / Enhancement Ideas
- Automated Mod Installation: Incorporate a mechanism to automatically download a predefined list of mods from sources like Modrinth or CurseForge.
- Firewall Rule Management: Add an optional function to automatically configure
ufw
orfirewalld
to open the required server ports.
Conclusion
This automation script provides a robust and efficient solution for deploying a Minecraft Fabric server. By handling dependency installation, user management, service configuration, and backups, it adheres to operational best practices and significantly reduces the administrative burden. The result is a stable, secure, and easily manageable server, ready for gameplay or development work.
References
For further information on Fabric and Minecraft server administration, consult the official documentation.
- Fabric Documentation: https://fabricmc.net/
- Minecraft Wiki (Server.properties): https://minecraft.fandom.com/wiki/Server.properties
- MCRCON: https://github.com/Tiiffi/mcrcon
- Minecraft: https://www.minecraft.net/en-us