← Back to Minecraft Documentation | Documentation Portal
This document outlines the complete procedure to construct the Minecraft Java Edition (Fabric) server infrastructure from a bare-metal Linux installation. This configuration emphasizes stability, security via network segmentation (Tailscale), and automated offsite backups.
Update package lists and install necessary tools: OpenJDK 21 (Headless), Screen (for background console management), UFW (firewall), Zip/Unzip, Curl, and Rclone (for backups).
sudo apt update && sudo apt upgrade -y sudo apt install openjdk-21-jre-headless screen ufw zip unzip curl -y sudo curl https://rclone.org/install.sh | sudo bash
For security, the server should never run as root. Create a dedicated user (e.g., mcserver).
sudo adduser mcserver # Follow prompts to set a strong password.
Switch to the user:
su - mcserver
Implement a "Default Deny" policy. Only allow standard Minecraft traffic directly from the public internet. SSH access should be restricted to the local LAN or Tailscale network interfaces.
# Ensure you are logged in as a sudo user for these commands sudo ufw default deny incoming sudo ufw default allow outgoing # Allow public Minecraft traffic (Default TCP 25565) sudo ufw allow 25565/tcp # Enable firewall sudo ufw enable
Install Tailscale so the server joins your private administrative network. This allows you to SSH into the server without exposing Port 22 to the public internet.
curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up # Follow the link provided to authenticate the machine.
Tell UFW to allow all traffic coming from other devices on your Tailscale network.
sudo ufw allow in on tailscale0
Log into the network edge router. Forward TCP Port 25565 to the server's local LAN IP address.
Ensure you are logged in as the dedicated user (mcserver). Create the directory structure.
mkdir -p ~/fabric_server cd ~/fabric_server
Visit fabricmc.net to grab the latest installer URL or use curl. (Example below uses a generic name, check site for actual current version).
curl -OJ https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.0/fabric-installer-1.0.0.jar
Run the installer jar to download the vanilla Minecraft server jar and generate the necessary Fabric libraries.
# Replace installer jar name with actual downloaded version java -jar fabric-installer-*.jar server -downloadMinecraft
Note: You may delete the installer jar after this step.
Attempt to run the server once to generate the EULA file, then accept it.
java -Xmx2G -jar fabric-server-launch.jar nogui # It will exit immediately. sed -i 's/eula=false/eula=true/g' eula.txt
Edit `server.properties` to configure game settings.
nano server.properties
Key requirements:
server-port=25565white-list=true (Highly recommended for private servers)Create a script to handle Java arguments and launch the server inside a detached screen session. This is crucial for systemd integration.
nano ~/fabric_server/start.sh
File Content:
#!/bin/bash # Minecraft Server Startup Script SERVER_DIR=/home/mcserver/fabric_server JAR_NAME=fabric-server-launch.jar # RAM Allocation (adjust based on available system RAM) RAM=4G cd "$SERVER_DIR" # -DmS starts a detached screen session named 'mcserver' /usr/bin/screen -DmS mcserver /usr/bin/java -Xmx$RAM -Xms$RAM -jar $JAR_NAME nogui
Make the script executable:
chmod +x ~/fabric_server/start.sh
Create a systemd unit file to manage the server as a native Linux service. This handles auto-start on boot and graceful shutdowns.
As a sudo user:
sudo nano /etc/systemd/system/minecraft.service
File Content: (Ensure paths and User match your setup)
[Unit] Description=Fabric Minecraft Server After=network.target [Service] # The user created in Step 1.3 User=mcserver Group=mcserver WorkingDirectory=/home/mcserver/fabric_server # Start Command uses the script created in Step 4.2 ExecStart=/home/mcserver/fabric_server/start.sh # Stop Command sends the "stop" command into the running screen session ExecStop=/usr/bin/screen -p 0 -S mcserver -X eval 'stuff "stop"\015' # Restart policy Restart=on-failure RestartSec=10s [Install] WantedBy=multi-user.target
sudo systemctl daemon-reload sudo systemctl enable minecraft sudo systemctl start minecraft
Verify status:
sudo systemctl status minecraft
To view logs or issue commands, attach to the running screen session as the service user.
# Switch to service user if needed su - mcserver # Attach to session screen -r mcserver
To detach (leave running): Press Ctrl + A, then press D.
Use standard systemctl commands (requires sudo privileges):
sudo systemctl stop minecraft sudo systemctl restart minecraft
Backups are handled by a custom script that stops game writes, zips the world data, and uploads it to Google Drive using Rclone.
Run the configuration wizard to authorize Google Drive access. Name the remote gdrive.
rclone config # Follow prompts: n (new remote) -> name: gdrive -> Storage Number for Drive -> Follow auth steps.
As the service user (mcserver), create the automation script.
mkdir -p ~/scripts mkdir -p ~/backups nano ~/scripts/backup_world.sh
File Content:
#!/bin/bash
# --- CONFIG ---
SERVER_DIR="/home/mcserver/fabric_server"
WORLD_NAME="world"
BACKUP_DIR="/home/mcserver/backups"
REMOTE_NAME="gdrive"
# Use underscores, avoid colons in remote folder names for cross-OS compatibility
REMOTE_PATH="backups/minecraft_25565"
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M")
ZIP_NAME="world_${TIMESTAMP}.zip"
# --- EXECUTION ---
echo "Starting backup process for $TIMESTAMP..."
# Optional: Send 'save-all' and 'save-off' to console via screen before zipping for perfect data integrity
# /usr/bin/screen -p 0 -S mcserver -X eval 'stuff "save-all"\015'
# sleep 5
# /usr/bin/screen -p 0 -S mcserver -X eval 'stuff "save-off"\015'
# Zip the world folder relative to the server directory
cd "$SERVER_DIR"
zip -r -q "$BACKUP_DIR/$ZIP_NAME" "$WORLD_NAME"
# Optional: Turn game saving back on
# /usr/bin/screen -p 0 -S mcserver -X eval 'stuff "save-on"\015'
echo "Uploading $ZIP_NAME to remote..."
# --min-age ensures file is finished writing before upload attempts
rclone copy "$BACKUP_DIR/$ZIP_NAME" "$REMOTE_NAME:$REMOTE_PATH" --min-age 1s -P
# Cleanup local zip to save space
rm "$BACKUP_DIR/$ZIP_NAME"
echo "Backup complete."
Make executable:
chmod +x ~/scripts/backup_world.sh
Open the crontab for the service user:
crontab -e
Add the following line to run the backup daily at 4:00 AM:
0 4 * * * /home/mcserver/scripts/backup_world.sh >> /home/mcserver/scripts/backup.log 2>&1