Posts here are mostly step-by-step guides on how to replicate something I have set up in the past. Read over my About page to see how I show commands/output and read the disclaimer.
Base OS
Install Ubuntu 22.04 Server. At setup, create your preferred user for managing the server. We will create a user specific to the Minecraft service later.
Update and install some software.
[root]$ export NEEDRESTART_MODE=a [root]$ apt update && apt -y dist-upgrade [root]$ apt -y install git htop openjdk-17-jre-headless screen rdiff-backup
Minecraft Server Setup
Add a user.
[root]$ useradd -m -s /bin/bash bukkit
Create some directories.
[bukkit]$ mkdir -p /home/bukkit/{minecraft,mcbackup,scripts}
Download the server jar.
[bukkit]$ cd /home/bukkit/minecraft [bukkit]$ wget https://download.getbukkit.org/craftbukkit/craftbukkit-1.20.4.jar [bukkit]$ ln -s craftbukkit-1.20.4.jar minecraft_server.jar
Create the eula file. This is necessary to run for the first time.
[bukkit]$ echo "eula=true" > /home/bukkit/minecraft/eula.txt
Test run? You can do that by running this:
[bukkit]$ java -Xmx1024M -Xms1024M -jar /home/bukkit/minecraft/minecraft_server.jar nogui
Once the world generates, feel free to join from the client. This is a good checkpoint before moving into the service/backup configurations.
Once done, type “stop” into the running server to stop it.
Systemd Service
The service is pretty easy, just basically creating a few files. You don’t have to use vim; use your editor of choice and paste in the contents for each file.
This file allows you to start/stop/monitor the service and logs.
[root]$ vim /etc/systemd/system/minecraft.service
File contents:
[Unit] Description=Minecraft Server [Service] Type=simple WorkingDirectory=/home/bukkit/minecraft ExecStart=java -Xmx1024M -Xms1024M -jar /home/bukkit/minecraft/minecraft_server.jar nogui ExecStop=/home/bukkit/scripts/stop.sh KillSignal=SIGINT SendSIGKILL=no TimeoutStopSec=300 User=bukkit Restart=on-failure Sockets=minecraft.socket StandardInput=socket StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
The stop command needs to be in its own script for some reason.
[bukkit]$ vim /home/bukkit/scripts/stop.sh
#!/usr/bin/bash echo "stop" > /run/minecraft.stdin sleep 45
[bukkit]$ chmod +x /home/bukkit/scripts/stop.sh
Adding a socket that will allow sending commands to the running service. Finding how to do this is what finally got me away from using “screen” to hold the running process.
[root]$ vim /etc/systemd/system/minecraft.socket
File contents:
[Unit] PartOf=minecraft.service [Socket] ListenFIFO=%t/minecraft.stdin
Allow the bukkit user to manage the service
The following will walk you through creating a sudoers file that will allow the bukkit user to run service commands, but only for the minecraft service.
[root]$ vim /etc/sudoers.d/bukkit
Add this:
bukkit ALL=(ALL) NOPASSWD:/usr/bin/systemctl start minecraft bukkit ALL=(ALL) NOPASSWD:/usr/bin/systemctl stop minecraft bukkit ALL=(ALL) NOPASSWD:/usr/bin/systemctl restart minecraft bukkit ALL=(ALL) NOPASSWD:/usr/bin/systemctl status minecraft bukkit ALL=(ALL) NOPASSWD:/usr/bin/journalctl -u minecraft -f
Fix the permissions.
[root]$ chmod 0440 /etc/sudoers.d/bukkit
Command Reference
Starts the service if it wasn’t running.
[bukkit]$ sudo systemctl start minecraft
Stops the service.
[bukkit]$ sudo systemctl stop minecraft
Restarts the service.
[bukkit]$ sudo systemctl restart minecraft
Get the status of the service.
[bukkit]$ sudo systemctl status minecraft
Watch the log output.
[bukkit]$ sudo journalctl -u minecraft -f
Send a command to the service.
[bukkit]$ echo "say hellooooooo" > /run/minecraft.stdin
Most of the Systemd configuration was found in this StackExchange Answer.
Local Backup
I backup the VM routinely, however, I backup the world files hourly. This can be done locally.
Create this file.
[bukkit]$ vim /home/bukkit/scripts/mcbackup.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/bash # remove old backups # rdiff-backup --remove-older-than 7D --force /home/bukkit/mcbackup/ # save any chunks in memory # echo "save-all" > /run/minecraft.stdin sleep 10 # disable level saving while the backup runs # echo "say ** Backup Yo Stuffz! May lag a sec during backup. **" > /run/minecraft.stdin echo "save-off" > /run/minecraft.stdin # run the local backup # rdiff-backup --exclude /home/bukkit/minecraft/plugins/dynmap/web /home/bukkit/minecraft /home/bukkit/mcbackup # enable disk writes again # echo "save-on" > /run/minecraft.stdin echo "say ** Done **" > /run/minecraft.stdin |
[bukkit]$ chmod +x /home/bukkit/scripts/mcbackup.sh
Consider adding the script to bukkit’s crontab.
Test a Restore
Run the script manually a few times or let the cron go a few times. Then run the below rdiff-backup command (just the first line) and see the output.
[bukkit]$ rdiff-backup --list-increments ~/mcbackup Found 3 increments: increments.2024-01-13T03:29:55Z.dir Sat Jan 13 03:29:55 2024 increments.2024-01-13T03:30:46Z.dir Sat Jan 13 03:30:46 2024 increments.2024-01-13T03:32:21Z.dir Sat Jan 13 03:32:21 2024 Current mirror: Sat Jan 13 03:32:33 2024
The below command will restore the most recent backup available (Sat Jan 13 03:32:33 2024) based on the above output. Useful if you just died or something 🙂
[bukkit]$ sudo systemctl stop minecraft [bukkit]$ rdiff-backup --force -r now /home/bukkit/mcbackup /home/bukkit/minecraft [bukkit]$ sudo systemctl start minecraft
Refer to rdiff-backup documentation for more restore options.