Why restores fail in practice
Most restore failures are not caused by the backup archive itself. They happen because the restore process is sloppy:
- the server is still running
- the target directory is not what the admin thinks it is
- the backup is restored into incompatible software without checking
This runbook avoids those mistakes.
Before you touch data
Write down three things first:
- where the live world data currently lives
- which backup you plan to restore
- whether you need a full server restore or only a world rollback
If you use itzg/mc-backup, the default live directory is usually /data and the default backup location is usually /backups.
Step 1: Stop the server cleanly
Do not restore over a running world.
Stop the backup sidecar and Minecraft service through Compose:
docker compose stop backup mc
Compose sends the normal stop signal and prevents the service's restart policy from immediately bringing the container back. Stopping the backup sidecar as well ensures it cannot start another job while you move its source directory. If your service is named backups instead, use that name.
Then confirm it is really down:
docker compose ps
Step 2: Protect the current state before restoring
Even during an incident, avoid a one-way operation. Move the current directory aside instead of overwriting it:
mv ./data ./data.pre-restore.$(date +%F-%H%M%S)
mkdir ./data
sudo chown 1000:1000 ./data
This gives you a rollback path if you picked the wrong backup. 1000:1000 is the default container UID/GID; use the values from your Compose file if you deliberately changed them.
Step 3: Choose the restore method
If you use itzg/mc-backup, the image includes restore scripts.
For tar-based backups, the current restore-tar-backup helper:
- only restores when
/datais empty - selects the newest file from
/backups - extracts that file into
/data
That safety check is useful, but the automatic selection is not enough for an incident runbook. Give the helper a directory that contains only the archive you deliberately selected.
Step 4: Restore into the correct target
Add this recovery-only service to your Compose file. The profile prevents it from running during a normal docker compose up:
services:
restore-backup:
profiles: ["recovery"]
image: itzg/mc-backup:latest
user: "1000"
restart: "no"
entrypoint: restore-tar-backup
volumes:
- ./data:/data
- ${RESTORE_SOURCE:-./restore-source}:/backups:ro
List the available archives and inspect the selected archive before extracting anything:
ls -lht ./backups
tar -tf ./backups/CHOSEN_BACKUP.tar.gz | sed -n '1,40p'
Create a fresh selection directory containing exactly that archive, then run the helper:
restore_source="./restore-source-$(date +%F-%H%M%S)"
mkdir "$restore_source"
cp ./backups/CHOSEN_BACKUP.tar.gz "$restore_source"/
RESTORE_SOURCE="$restore_source" docker compose --profile recovery run --rm restore-backup
The command should print the archive it restored. If it prints No restore needed, /data was not empty and you should stop instead of forcing an in-place extraction.
If you prefer a staging restore, restore into ./data-restore-test first and inspect it before swapping it into production.
Step 5: Start the server and validate
Bring the server back:
docker compose up -d mc
docker compose logs -f mc
Start the backup sidecar again only after you have confirmed that the restored server is healthy:
docker compose up -d backup
Validate three things:
- the server starts without world corruption errors
- the expected world name and player data are present
- the in-game state matches the point in time you intended to restore
For important servers, log in and verify a known landmark or build instead of assuming the restore is correct.
Compatibility checks you should not skip
Restoring world data is not only a file operation. It also depends on the software stack around it.
Check:
- Minecraft version
- server type
- plugins or mods that change world data
Restore the software versions that created the backup first, validate the world, and perform a separate controlled upgrade afterwards. Paper's current migration documentation also warns that world-layout differences around 26.1 can make direct switches between Paper and CraftBukkit/Spigot unsafe. Do not combine a disaster restore with a server-type migration.
Common mistakes
| Symptom | Likely cause | Fix |
|---|---|---|
| Restore does nothing | Target directory was not empty | Prepare a clean restore target |
| Restored world crashes on boot | Version or plugin mismatch | Re-check the software stack used when the backup was created |
| Wrong world came back | Wrong archive selected or backup naming unclear | Standardize naming and document retention |
| No safe fallback after a bad restore | Current state was overwritten too early | Always snapshot or copy current data first |
FAQ
Should I test restores even when nothing is broken?
Yes. A restore process that only exists in theory is not a reliable backup strategy.
Is it enough to restore only the world folder?
Sometimes, but not always. If plugins store important state elsewhere under /data, a partial restore can create inconsistent behavior.
Next steps
- If you do not have automated backups yet, set up docker-mc-backup first.
- If you host on Hetzner, understand the limits of infrastructure snapshots in the Hetzner snapshots guide.
- If you want safer operational control before and after a restore, use RCON and console access in Docker.