# Backup & restore ## Schedule Host cron, daily 02:00, 7-day retention. Script: [`scripts/backup.sh`](../scripts/backup.sh) (deployed to `/opt/docker/backup.sh` on host). Output: `/opt/backups/YYYYMMDD_HHMMSS/`. Backs up the whole nullstone Docker stack; the Minecraft block (lines 80-117 of backup.sh) handles MC. ## Strategy | Server state | Backup type | Method | |--------------|-------------|--------| | Running | World snapshot + configs | `docker exec` tars worlds inside container (consistent), then `docker cp` out. Configs tarred from host. | | Stopped | Full archive | Single tar of `/opt/docker/minecraft/` (worlds + plugins + configs). | ## Manual backup ```bash ssh user@192.168.0.100 /opt/docker/backup.sh ``` ## Manual archive (full server, while stopped) ```bash ssh user@192.168.0.100 'cd /opt/docker/minecraft && docker compose down' ssh user@192.168.0.100 'tar czf - -C /opt/docker minecraft' > minecraft-backup-$(date +%F).tar.gz ssh user@192.168.0.100 'cd /opt/docker/minecraft && docker compose up -d' ``` ## Restore ```bash # Stop running server ssh user@192.168.0.100 'cd /opt/docker/minecraft && docker compose down' # Move current dir aside ssh user@192.168.0.100 'mv /opt/docker/minecraft /opt/docker/minecraft.broken' # Extract backup scp minecraft-backup-YYYY-MM-DD.tar.gz user@192.168.0.100:/tmp/ ssh user@192.168.0.100 'cd /opt/docker && tar xzf /tmp/minecraft-backup-YYYY-MM-DD.tar.gz' # Re-apply perms (userns-remap) ssh user@192.168.0.100 'chmod -R 777 /opt/docker/minecraft' # Boot ssh user@192.168.0.100 'cd /opt/docker/minecraft && docker compose up -d' ``` ## What's NOT in repo backups - Plugin jars: re-downloaded fresh on each boot via `MODRINTH_PROJECTS` / `SPIGET_RESOURCES`. - World data: only in `/opt/backups/` archives, never committed to git (binary, large, frequently changing). - Player data (`usercache.json`, `ops.json`, `whitelist.json`): committed to repo *as snapshots only*; live state lives on host.