How to Set Up Automatic Offsite Backups on Your MU Server
Build an automatic backup flow that copies your MU server's database and configuration to external storage, with rotation, integrity checks, and failure alerts.
Every MU Online administrator lives under the same silent threat: a disk that fails, a wrong command in SQL, a ransomware attack, or a provider that simply vanishes with your machine. The database holds accounts, characters, inventories, guilds, resets, and the server's entire economic history. Losi
Every MU Online administrator lives under the same silent threat: a disk that fails, a wrong command in SQL, a ransomware attack, or a provider that simply vanishes with your machine. The database holds accounts, characters, inventories, guilds, resets, and the server's entire economic history. Losing that is not a technical problem — it is the end of the project and of the community's trust. This tutorial shows how to build an automatic offsite backup flow, meaning one that copies the critical data off the source machine, on a schedule, verified and with rotation. The focus here is not just "generating a .bak", but ensuring there is always a recoverable copy somewhere that will survive the death of the main server. The paths, versions, and values cited are examples and vary by provider/version — what matters is understanding the concept and adapting it to your setup.
Prerequisites
Before automating anything, make sure the basics are in place. This tutorial assumes a MU server already running (if you are still building yours, see the guide on how to create a MU Online server).
- Administrative access to the VPS or machine hosting the server (RDP on Windows, or SSH on Linux).
- A working database — usually SQL Server (2008/2014/2019 are common on MU S6) or MySQL/MariaDB on more modern servers.
- A defined external destination: cloud (object storage, drive), a second VPS, or remote storage reachable over SFTP/rclone.
- A synchronization tool installed. rclone is the most versatile choice because it speaks to dozens of providers; native SFTP works too.
- Enough local disk space to generate the compressed file before uploading (rule of thumb: 2x the current database size).
- A dedicated service user for the backup, with no privileges beyond what is needed.
Understand what really needs to be copied
The most common mistake is thinking "server backup" is just the database. A MU server has two categories of critical data, and the configuration is not inside SQL.
| Category | What it contains | Where it lives (example) |
|---|---|---|
| Database | Accounts, characters, inventory, guilds, resets, economy | SQL Server MuOnline / MySQL |
| GameServer configuration | Spots, drops per map, events, rates | GameServer\Data\ (.txt/.ini/.xml files) |
| ConnectServer / JoinServer | IPs, server list, ports | .ini files in the server folder |
| Panel/website | Site config, cash shop, integrations | Web folder + site database |
| Custom scripts | NPCs, events, and quests you edited | GameServer data folders |
If you customized spots on endgame maps or an event's drops, that data lives in GameServer text files — a SQL-only backup will not recover it. Treat the server's data folder as a mandatory part of the backup.
Step 1 — Generate a consistent database backup
The backup must be a consistent "snapshot" of the database, not a copy of files open and in use. Never copy the .mdf/.ldf files (SQL) or the MySQL data directory "by hand" while the service is running — that produces corrupted files.
On SQL Server, use the native command, which guarantees consistency and even compresses:
BACKUP DATABASE [MuOnline]
TO DISK = N'D:\Backups\MuOnline\MuOnline_full.bak'
WITH
COMPRESSION, -- greatly reduces the file size
CHECKSUM, -- writes an integrity check
INIT,
STATS = 10,
NAME = N'Backup completo MuOnline';
On MySQL/MariaDB, mysqldump generates a consistent logical dump:
mysqldump --single-transaction --routines --triggers \
-u backup_user -p muonline > /backups/muonline_$(date +%F).sql
The --single-transaction parameter avoids locking the tables during the dump on InnoDB databases. The goal of this step is to end up with a single file per run, dated in the name, ready to be compressed and uploaded.
Step 2 — Package the database and configuration together
A useful backup puts the database and the configuration folders in the same dated package. That way, at restore time, everything came from the same moment. A simple script handles this on Windows with PowerShell:
# gera-pacote.ps1 — bundles .bak + the Data folder into a dated zip
$stamp = Get-Date -Format 'yyyyMMdd_HHmm'
$destino = "D:\Backups\Pacotes\mu_$stamp.zip"
# 1) run the SQL backup (procedure or direct command)
sqlcmd -S localhost -Q "BACKUP DATABASE [MuOnline] TO DISK='D:\Backups\MuOnline\MuOnline_full.bak' WITH COMPRESSION, CHECKSUM, INIT"
# 2) package the .bak + the GameServer configuration folder
Compress-Archive -Path @(
"D:\Backups\MuOnline\MuOnline_full.bak",
"D:\MuServer\GameServer\Data"
) -DestinationPath $destino -Force
Write-Host "Package generated: $destino"
On Linux, the equivalent is a tar with the dump and the data folder:
tar -czf /backups/mu_$(date +%F_%H%M).tar.gz \
/backups/muonline_$(date +%F).sql \
/opt/muserver/GameServer/Data
Step 3 — Send it to the external destination with rclone
With the package ready locally, the offsite upload is the heart of this tutorial. rclone connects to practically any provider (drives, S3-compatible object storage, SFTP) with the same syntax. After running rclone config once to create the "remote", the upload is a single line:
# uploads the most recent package and keeps a log
$arquivo = Get-ChildItem "D:\Backups\Pacotes\*.zip" |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
rclone copy $arquivo.FullName "remote:backups/mu/" `
--bwlimit 8M ` # caps bandwidth so it does not drown out players
--log-file "D:\Backups\Logs\rclone.log" `
--log-level INFO
The --bwlimit parameter (example: 8 MB/s, tune it to your link) keeps the upload from consuming all the bandwidth and causing in-game lag. If you prefer pure SFTP to a second VPS, the concept is the same: transfer the dated package to a machine physically different from the source.
> An external destination is only truly external if it is on another machine/infrastructure. Copying to "another folder" or "another disk on the same VPS" does not protect against losing the entire machine.
Step 4 — Verify integrity before trusting it
Uploading a corrupted file is worse than having no backup, because it creates false security. Always validate. On SQL Server, the native check verifies the CHECKSUM without restoring:
RESTORE VERIFYONLY
FROM DISK = N'D:\Backups\MuOnline\MuOnline_full.bak'
WITH CHECKSUM;
For the uploaded package, compare the size and hash locally against the remote copy. rclone has a dedicated command that checks this automatically:
rclone check "D:\Backups\Pacotes\" "remote:backups/mu/" --one-way
If the hash matches, the file arrived intact. Record the result in the log of every run — that way, if something breaks in the middle of the night, you know exactly which was the last good backup.
Step 5 — Layered rotation and retention
Keeping everything forever fills the storage and makes it harder to find the right file in an emergency. Use layered retention, keeping more granularity for recent data:
remote:backups/mu/
├── diario/ → last 7 days
├── semanal/ → 1 per week, for 4 weeks
└── mensal/ → 1 per month, for 6 months
Cleaning up the old ones is also automatable. rclone removes files past a certain age with a single command:
# deletes daily backups older than 7 days at the external destination
rclone delete "remote:backups/mu/diario/" --min-age 7d
Locally, do the same rotation so you do not fill the VPS disk, keeping only the last few days before the upload.
Step 6 — Schedule automatic execution
A manual backup works while you remember; an automatic backup works while the server is on. On Windows, use the Task Scheduler pointing to the script:
- Open Task Scheduler (
taskschd.msc). - Create a task with a daily trigger in the early hours (example: 03:00).
- Action: start
powershell.exewith arguments-NonInteractive -ExecutionPolicy Bypass -File "D:\Scripts\gera-pacote.ps1". - Check "Run whether the user is logged on or not" and use the dedicated service user.
- In the settings, enable "Run task as soon as possible after a scheduled start is missed".
On Linux, one line in crontab -e handles it:
# 03:00 every day: generate the package and upload
0 3 * * * /opt/scripts/backup-mu.sh >> /var/log/backup-mu.log 2>&1
Step 7 — Failure alerts
You need to know when a backup did not happen, and not find out on the day of the disaster. Add an alert at the end of the flow, fired only on error. A simple email example in PowerShell:
if ($LASTEXITCODE -ne 0) {
Send-MailMessage -SmtpServer "smtp.seuprovedor.com" -Port 587 -UseSsl `
-From "[email protected]" -To "[email protected]" `
-Subject "FAILURE in the MU offsite backup" `
-Body "The offsite backup failed at $(Get-Date). Check the log." `
-Encoding UTF8
}
Many administrators prefer a webhook to the team's Discord — the concept is the same: turn a silent error into a notification someone will actually see.
Common errors and fixes
| Error / Symptom | Likely cause | Fix |
|---|---|---|
| Backup file corrupted on restore | Copying database files with the service running | Always use BACKUP DATABASE / mysqldump, never copy .mdf/.ldf while hot |
| Upload makes the game lag | The upload consumes all the upload bandwidth | Cap the bandwidth (--bwlimit) and schedule it for off-peak hours |
| VPS disk fills and the server goes down | Local backups are never removed | Apply local rotation (delete files older than X days) |
| Backup runs but never reaches the cloud | Expired remote credential or wrong config | Test with rclone lsd remote: and check the log; recreate the OAuth token |
| Event settings "disappeared" after restoring | Only SQL was saved, not the Data folder | Always include GameServer\Data in the package |
| Scheduled task does not fire | Running as a user without permission, or the VPS was rebooted | Use a service account and check "run if the start is missed" |
Launch checklist
- Database backup generated with the native command (with compression and checksum)
GameServer\Datafolder and ConnectServer/JoinServer configs included in the package- External destination on a different machine/infrastructure from the source
- Automatic upload with bandwidth limit configured
- Integrity check (
RESTORE VERIFYONLY/rclone check) in the flow - Layered rotation and retention (daily/weekly/monthly) active
- Local rotation of the VPS disk active
- Automatic scheduling running under a dedicated service user
- Failure alert by email or Discord working
- Monthly restore test on a separate database scheduled
With this flow you stop depending on your own memory and gain a system that protects the server even while you sleep: database and configuration packaged, sent off the machine, verified, rotated, and monitored. It is the difference between a hardware mishap being a one-hour scare or the end of your server.
Frequently asked questions
Does a local backup on the same server disk count as a backup?
It does not count as real protection. If the VPS disk fails, gets corrupted, or is hit by ransomware, you lose the server and the backup at the same time. A valid backup is one that leaves the source machine for an external destination (cloud, another VPS, separate storage). The ideal is to follow the 3-2-1 rule: three copies, on two types of media, with one offsite.
How often should I send the backup off the server?
It depends on activity. For active servers, the most common setup is a full daily backup in the early hours with an external upload right after. Servers with a heavy internal economy (item trading, donations) benefit from external copies every 4-6 hours. Adjust based on how much player progress you are willing to lose in a worst-case scenario.
Do I have to pay for cloud storage to have an offsite backup?
Not necessarily. Many administrators start with free tiers of cloud services or with a cheap second VPS receiving the files over SFTP. As the database grows, the cost of paid storage tends to be trivial next to the loss of months of player progress. The figures cited here are examples and vary by provider.
Can sending the backup offsite slow the server down?
The bottleneck is rarely the CPU and more often the disk and the upload link. To reduce the impact, generate the compressed file on a separate disk before sending, schedule the upload for off-peak hours, and cap the transfer tool's bandwidth. That way the offsite backup runs without competing with players online.
How do I know the offsite backup will actually work when I need it?
A backup that has never been restored is just a hope. Do a monthly restore test on a separate database, validate the file's integrity before uploading, and check the log of every run. Without that habit, you only find out the backup was broken on the day of the disaster.