Automatic restarts for a Minecraft server
Minecraft does not strictly require restarts, but it runs better with them. Over a long uptime memory becomes fragmented, chunk data piles up in ways the garbage collector copes with less and less well, and leaky plugins are common enough that restarting every night is cheaper than hunting down the culprit.
When should it restart?
Put {{minutes}} wherever the number of minutes left should appear.
What happens, in order
- Job startsWarn
say Server restarting in 15 min - 10 min beforeWarn
say Server restarting in 10 min - 5 min beforeWarn
say Server restarting in 5 min - 1 min beforeWarn
say Server restarting in 1 min - Restart timeSave
save-all - Restart timeStop
stop
stop flushes the world to disk on its way out, so the explicit save-all is belt and braces rather than strictly required. Keep it anyway — it costs nothing and it means the save has already happened if the shutdown hangs.
The crontab line
Moved 15 minutes ahead of the time you picked, so the restart happens at that time instead of 15 minutes later.
45 3 * * * /opt/restart-minecraft.sh
The script it runs
Save it as /opt/restart-minecraft.sh and mark it executable. It expects rcon-cli on the path and takes the password from an environment variable instead of storing it in the file.
#!/usr/bin/env bash
set -euo pipefail
# Scheduled restart for Minecraft.
# Generated by spawnbench.com/restart-scheduler
# The password stays out of this file. Put it in the environment, or in a
# file only root can read, and export it before this script runs.
RCON_HOST="${RCON_HOST:-127.0.0.1}"
RCON_PORT="${RCON_PORT:-25575}"
: "${RCON_PASSWORD:?set RCON_PASSWORD before running}"
send() {
rcon-cli --host "$RCON_HOST" --port "$RCON_PORT" --password "$RCON_PASSWORD" "$1"
}
# 15 minute warning
send 'say Server restarting in 15 min'
sleep 300
# 10 minute warning
send 'say Server restarting in 10 min'
sleep 300
# 5 minute warning
send 'say Server restarting in 5 min'
sleep 240
# 1 minute warning
send 'say Server restarting in 1 min'
sleep 60
# Flush the world to disk
send 'save-all'
sleep 10
# Shut down cleanly
send 'stop'
# Give the process time to finish writing before anything restarts it.
sleep 30
systemctl start minecraft 2>/dev/null || trueHeads up: cron follows the server clock, not your local time. Check with timedatectl first. A container set to UTC and an admin living in Europe differ by two hours in summer and by one in winter, so 04:00 may not be the 04:00 you had in mind.
Advertisement
What is different about Minecraft
Issue save-all and wait for it to complete before sending stop. Shutting down saves anyway, so normally the extra save changes nothing — but if the process freezes on exit, that redundant save is what separates losing nothing from losing everything since the last autosave. Behind a proxy like Velocity or BungeeCord, restart the backend servers one after another instead of all at once, so players get moved across instead of kicked.
Advertisement
Turning on RCON for the warnings
The warnings and the stop are sent over RCON, which is off until three lines in server.properties are set: enable-rcon=true, rcon.port (25575 unless you change it) and rcon.password. Use a long random password and keep the RCON port closed on your router; the script talks to it from the same machine, so it never needs to be reachable from outside.
No RCON? Use the console session
If the server runs inside tmux, a script can type into its console directly instead. tmux send-keys -t minecraft "say Restarting in 5 minutes" Enter sends the warning, and the same pattern sends save-all and stop. This avoids opening RCON at all, at the cost of depending on the session being named consistently.
Backing up without stopping
A restart is a natural moment for a backup, but you can also take one while the server runs. Send save-off so the server stops writing to the world, then save-all flush to finish writing everything pending, copy the world folder, and send save-on. Copying without save-off risks a backup caught halfway through a chunk being written.