Minecraft Server Deployment: An Automation Primer
Minecraft Server Deployment: An Automation Primer
In the landscape of multiplayer gaming, dedicated servers offer unparalleled control and customisation for players. However, the manual setup process is often repetitive, time-consuming, and prone to error. This post introduces a bash script designed to automate the deployment of a Minecraft: Java Edition server on Ubuntu systems, providing a secure, consistent, and efficient foundation for your gaming world.
Purpose
The primary purpose of this automation script is to streamline the installation and configuration of a dedicated Minecraft server. Manually performing these steps is a tedious process that can introduce security vulnerabilities if not executed correctly.
TL;DR: Here’s a bash script to fully automate the setup of a secure Minecraft: Java Edition server on Ubuntu: https://gist.github.com/CraigWilsonOZ/983bd539a1bbc17a1a726e63b885a6f6
Use Cases
This script adds value across several practical scenarios:
- Home Labs and Personal Servers: Enthusiasts can quickly deploy a personal Minecraft server for friends and family without needing extensive Linux administration knowledge. The script’s rerunnable nature means it can be used to repair or update an existing installation.
- Developer and Content Creator Test Benches: Mod developers, plugin creators, and content creators require clean, repeatable server environments for testing. This automation allows for the rapid creation and destruction of identical server instances, ensuring consistent test results.
- Educational Environments: The script serves as a practical example for teaching shell scripting, automation principles, and basic Linux server management in a context that is engaging for students.
- Compliance and Standardisation: For small communities or groups that run multiple servers, the script enforces a standard configuration, ensuring that all servers adhere to the same security and operational baseline.
Prerequisites
To ensure the successful execution of the script, the following prerequisites must be met:
Requirement | Details |
---|---|
Operating System | A Debian-based Linux distribution. Tested on Ubuntu 24.04. |
Software | openjdk-21-jre-headless , git , build-essential , cron . |
Permissions | The script must be executed with root privileges (sudo ). |
Network Access | Outbound internet access is required to download the Minecraft server JAR file from Mojang’s servers and clone the mcrcon repository from GitHub. |
How the topic Works
The script follows a structured workflow to ensure a reliable and idempotent setup, meaning it can be run multiple times without causing adverse effects. If a component is already correctly configured, the script will skip that step.
- Initial Checks & Configuration: The script first verifies it is running with root privileges. It then defines a series of variables for user names, installation directories, and server settings.
- Dependency Installation: It updates the package manager and installs essential software packages required for running the Minecraft server and supporting tools.
- User and Directory Creation: A dedicated, unprivileged system user (
minecraft
) is created to isolate the server process, a recognised security best practice [1]. It then creates the necessary directory structure (/opt/minecraft
) and assigns appropriate ownership. - Server Download and Configuration: The script downloads the official Minecraft server JAR file and automatically accepts the End User Licence Agreement (EULA). It proceeds to generate a
server.properties
file, populating it with predefined settings, including a securely generated random password for RCON (remote console) access. - Tooling Setup: It clones and compiles
mcrcon
, a utility for remotely administering the Minecraft server. Helper scripts are then created to manage the server, connect via RCON, and perform backups. - Service and Backup Automation: A
systemd
service file is created to manage the Minecraft server as a background process, enabling it to start on boot and restart automatically on failure. A corresponding cron job is scheduled to run a daily backup script, which archives the server world and configuration files. - Finalisation: The script reloads the
systemd
daemon, enables and starts theminecraft
service, and outputs the RCON password and connection instructions to the administrator.
Parameter Reference
The following table details the configuration variables at the top of the script that can be customised by the administrator.
Parameter | Default Value | Data Type | Description |
---|---|---|---|
MINECRAFT_USER |
“minecraft” | String | The dedicated user to run the server. |
INSTALL_DIR |
“/opt/minecraft” | String | The base directory for all server files. |
SERVER_DIR |
“$INSTALL_DIR/server” | String | The directory containing the server JAR and world data. |
MINECRAFT_JAR_URL |
Mojang URL for 1.21.7 | String | The direct download link for the server JAR file. |
MAX_MEMORY |
“8192M” | String | Maximum Java heap size (e.g., “1024M”, “4G”). |
MIN_MEMORY |
“8192M” | String | Initial Java heap size. |
MINECRAFT_PORT |
“25565” | Integer | The network port for players to connect to. |
RCON_PORT |
“25575” | Integer | The network port for remote console (RCON) access. |
MAX_PLAYERS |
“20” | Integer | The maximum number of players allowed on the server. |
JDK_VERSION |
“openjdk-21-jre-headless” | String | The specific OpenJDK package to be installed. |
Quick-Start Guide
- Download the script:
wget -O setup-minecraft.sh <URL_TO_YOUR_SCRIPT_HOSTING>
- Make the script executable:
chmod +x setup-minecraft.sh
- Run the script with root privileges:
The script will handle all subsequent steps. Note the RCON password printed at the end of the execution.
sudo ./setup-minecraft.sh
The Script
#!/bin/bash
#==============================================================================
# Minecraft Java Server Setup Script
#
# Author: Craig Wilson
# Version: 1.2
# Last Modified: 2025-06-21
#
# Description:
# This script automates the setup of a Minecraft Java Edition 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.
#
# Features:
# - Installs necessary dependencies.
# - Creates a dedicated user and directories for the server.
# - Downloads the Minecraft server JAR file (if not present).
# - Configures server properties and RCON access.
# - Sets up scripts for starting the server and managing backups.
# - Schedules a daily backup via a cron job (if not present).
#
# Security Note:
# The scripts 'start-service-minecraft.sh' and 'stop-service-minecraft.sh'
# require the '$MINECRAFT_USER' user to have sudo privileges for systemctl.
#
# Tested on:
# - Ubuntu 24.04 (Lunar Lobster)
# - Minecraft Java Edition 1.21.7
# - Openjdk-21-jre-headless
#
#==============================================================================
# --- 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 Java Server Setup Script - v1.2
This script automates the setup of a Minecraft Java Edition server on a Debian-based system.
It is rerunnable and will skip steps that are already completed.
Usage:
sudo ./setup-minecraft.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="minecraft"
INSTALL_DIR="/opt/minecraft"
SERVER_DIR="$INSTALL_DIR/server"
TOOLS_DIR="$INSTALL_DIR/tools"
LOGS="$INSTALL_DIR/logs"
BACKUP_DIR="$INSTALL_DIR/backup"
MCRCON_DIR="$TOOLS_DIR/mcrcon"
MINECRAFT_JAR_URL="https://piston-data.mojang.com/v1/objects/05e4b48fbc01f0385adb74bcff9751d34552486c/server.jar"
# Addtional server.jar files can be found at
# https://gist.github.com/cliffano/77a982a7503669c3e1acb0a0cf6127e9
JAR_NAME="server.jar"
PASSWORD=$(date +%s | sha256sum | base64 | head -c 32 ; echo)
# Memory settings for the server.
# Adjust these values based on your system's available RAM.
MAX_MEMORY="8192M" # Maximum Heap memory allocation for the server
MIN_MEMORY="8192M" # Initial memory allocation for the server
# Minecraft and RCON ports.
MINECRAFT_PORT="25565"
RCON_PORT="25575"
# Maximum number of players allowed on the server.
MAX_PLAYERS="20"
# Open JDK version to use.
# Ensure this matches the installed version on your system.
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 Java Server Setup"
# === Install Dependencies ===
echo "▶ Installing dependencies..."
sudo apt-get update
sudo apt-get install -y $JDK_VERSION git build-essential cron
# === Create User and Directories ===
echo "▶ Ensuring user and directories exist..."
# Create the user; the || true part prevents errors on reruns
sudo useradd -r -m -U -d "$INSTALL_DIR" -s /bin/bash "$MINECRAFT_USER" || echo "✔ User '$MINECRAFT_USER' already exists."
# Create the main directories
sudo mkdir -p "$SERVER_DIR" "$TOOLS_DIR" "$BACKUP_DIR"
# NEW: Create a symbolic link for the logs
# First, remove the logs directory if it exists as a normal directory
if [ -d "$LOGS" ] && [ ! -L "$LOGS" ]; then
sudo rmdir "$LOGS"
fi
# Then, link the server's default log directory to our desired location
if [ ! -e "$LOGS" ]; then
echo "▶ Linking server logs directory..."
# The server will create /opt/minecraft/server/logs, so we link it to /opt/minecraft/logs
sudo -u "$MINECRAFT_USER" ln -s "$SERVER_DIR/logs" "$LOGS"
fi
# Set final ownership
sudo chown -R "$MINECRAFT_USER":"$MINECRAFT_USER" "$INSTALL_DIR"
# We use -h to change the ownership of the link itself, not what it points to
sudo chown -h "$MINECRAFT_USER":"$MINECRAFT_USER" "$LOGS"
# === Download Minecraft Server ===
if [ ! -f "$SERVER_DIR/$JAR_NAME" ]; then
echo "▶ Downloading Minecraft server JAR..."
sudo -u "$MINECRAFT_USER" wget -O "$SERVER_DIR/$JAR_NAME" "$MINECRAFT_JAR_URL"
else
echo "✔ Server JAR already exists. Skipping download."
fi
# === Accept EULA ===
echo "▶ Ensuring EULA is accepted..."
sudo -u "$MINECRAFT_USER" tee "$SERVER_DIR/eula.txt" > /dev/null <<EOF
eula=true
EOF
# === 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 # Give the server a moment to save
tar -cvpzf "$BACKUP_DIR/server-\$(date +%F-%H-%M).tar.gz" "$SERVER_DIR"
rcon "save-on"
echo "Backup complete."
# Delete older backups
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 "$JAR_NAME" nogui
EOF
sudo -u "$MINECRAFT_USER" tee "$TOOLS_DIR/start-service-minecraft.sh" > /dev/null <<EOF
#!/bin/bash
sudo systemctl start minecraft
EOF
sudo -u "$MINECRAFT_USER" tee "$TOOLS_DIR/stop-service-minecraft.sh" > /dev/null <<EOF
#!/bin/bash
sudo systemctl stop minecraft
EOF
# Make all scripts in the tools directory 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 | 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.service > /dev/null <<EOF
[Unit]
Description=Minecraft Java Server
After=network.target
[Service]
User=$MINECRAFT_USER
WorkingDirectory=$SERVER_DIR
ExecStart=/usr/bin/java -Xmx$MAX_MEMORY -Xms$MIN_MEMORY -jar $SERVER_DIR/$JAR_NAME 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; then
echo "▶ Starting and enabling the minecraft service..."
sudo systemctl enable --now minecraft
else
echo "✔ Minecraft service is already active. Ensuring it is enabled on boot."
sudo systemctl enable minecraft
echo "[!] The service definition or server properties may have changed. Run 'sudo systemctl restart minecraft' to apply all changes."
fi
echo ""
echo "[+] Setup Complete."
echo "[*] To connect to the server console, run: $TOOLS_DIR/connect-mcrcon.sh"
echo "[*] Your RCON password is: $PASSWORD"
echo ""
echo "### Security Note ###"
echo "To use the 'start/stop-service-minecraft.sh' scripts, you must grant sudo privileges."
echo "Run 'sudo visudo' and add the following line:"
echo "$MINECRAFT_USER ALL=(ALL) NOPASSWD: /usr/bin/systemctl start minecraft, /usr/bin/systemctl stop minecraft"
Security Considerations
- Privileged Operations: The script itself requires
sudo
to run. More specifically, for thestart-service-minecraft.sh
andstop-service-minecraft.sh
helper scripts to function, the unprivilegedminecraft
user requires passwordlesssudo
access to specificsystemctl
commands. This grants a non-interactive user the ability to start and stop a system service. This access must be strictly limited as shown in the script’s output to prevent privilege escalation. - Sensitive Data Handling: The script generates an RCON password and writes it in plain text to multiple files: the
server.properties
file and three helper scripts (connect-mcrcon.sh
,backup-minecraft.sh
, andminecraft.service
). The permissions of the installation directory are restricted to theminecraft
user, but any user with root access on the server can read these files. It is critical to secure the RCON password as it provides administrative access to the game server console. - Firewall Configuration: The script does not manage firewall rules. For the server to be accessible from the internet, the administrator must manually configure the system’s firewall (e.g.,
ufw
on Ubuntu) to allow incoming traffic on the specified Minecraft port (default: 25565/TCP).
Limitations
- Platform Specificity: The script is explicitly designed for Debian-based systems like Ubuntu that use the
apt
package manager andsystemd
. It will not function on other Linux distributions (e.g., CentOS, Arch Linux) or operating systems without significant modification. - Static Versioning: The script downloads a specific version of the Minecraft server JAR file via a hard-coded URL. To update the server to a new version, the administrator must manually update the
MINECRAFT_JAR_URL
variable in the script.
Future Work / Enhancement Ideas
- Version Management: Implement a function to automatically fetch the latest stable Minecraft server version URL from the Mojang API, allowing for easier upgrades.
- Firewall Automation: Add an optional function to automatically configure
ufw
orfirewalld
to open the necessary ports, with prompts to ensure the administrator consents to the changes.
Conclusion
This automation script provides a reliable method for deploying a Minecraft: Java Edition server. By codifying the setup process, it minimises manual effort, reduces configuration errors, and establishes a secure operational baseline. While designed for simplicity and immediate use, it also serves as a solid foundation that can be extended and adapted for more complex requirements.
References
For further information on Minecraft server administration, consult the official documentation.
- Minecraft Wiki (Server.properties): https://minecraft.fandom.com/wiki/Server.properties
- MCRCON: https://github.com/Tiiffi/mcrcon
- Minecraft: https://www.minecraft.net/en-us
[1] National Institute of Standards and Technology, “Guide to General Server Security,” SP 800-123, Jul. 2008. Accessed: Jul. 07, 2025. [Online]. Available: https://csrc.nist.gov/publications/detail/sp/800-123/final