Complete FiveM and Database Backup: Automated Routine

Set up automated backups for your FiveM server files and MySQL/MariaDB database with rotation, compression, and tested restore on a Linux VPS.

A production FiveM server handles player progress, in-game economy, whitelist data, and customizations that took months to put together. Losing any of that to a disk failure, human error, or an attack is expensive — in some communities, irrecoverable.

A manual WinSCP backup every Friday isn’t a strategy, it’s wishful thinking. This tutorial builds an automated routine that covers both sides that matter: server files (FXServer binary, the resources folder, server.cfg, txData) and the MySQL or MariaDB database used by frameworks like ESX, QBCore, or vRP. Estimated setup time: 25 to 40 minutes, including a restore test.

The target is Linux (Ubuntu 22.04 or 24.04 LTS) because that’s where most serious FiveM servers live. If you run Windows, the same concepts apply — swap cron for Task Scheduler and bash for PowerShell.

Prerequisites

Prerequisites

A Linux VPS running Ubuntu 22.04 LTS or 24.04 LTS with sudo access, FXServer already installed and running, MySQL/MariaDB installed with the framework database created. We recommend at least 20 GB free on disk to fit at least 7 days of retention.

System Ubuntu 22.04/24.04
Database MySQL 8.x or MariaDB 10.6+
FXServer Default folder /home/fivem
Suggested retention 7 daily + 4 weekly

Confirm that the MySQL user used by the framework has read permission on every table — a backup with partial permissions produces incomplete dumps without any obvious warning.

Directory Layout and Dedicated User

Before writing scripts, decide where backups will live and who runs them. Mixing backups with server files is a recipe for confusion and for deleting the wrong thing one day.

01

Create the root backup folder and two separate subdirectories — one for server files, another for database dumps:

sudo mkdir -p /var/backups/fivem/{files,database}
sudo chown -R fivem:fivem /var/backups/fivem
sudo chmod 750 /var/backups/fivem

The 750 permission ensures only the fivem user and group can read the contents. Database backups contain credentials and player data — they can’t be 755.

02

Create a dedicated MySQL user for backups with read-only permission. Never use the root user or the framework user in the backup script:

sudo mysql -u root -p

Inside the MySQL prompt:

CREATE USER 'fivem_backup'@'localhost' IDENTIFIED BY 'STRONG_PASSWORD_HERE';
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON *.* TO 'fivem_backup'@'localhost';
FLUSH PRIVILEGES;
EXIT;

That minimal set of privileges is what mysqldump needs to produce a complete and consistent dump.

03

Store the password in a configuration file readable only by its owner — that way it won’t show up in ps aux while the script runs:

sudo -u fivem tee /home/fivem/.my.cnf > /dev/null <<EOF
[client]
user=fivem_backup
password=STRONG_PASSWORD_HERE
EOF
sudo chmod 600 /home/fivem/.my.cnf

With that file in place, any mysql or mysqldump command run as the fivem user authenticates automatically, without passing -p on the command line.

Database Backup Script

The database dump is the most critical part and the one that needs the most care with consistency. A server with players online means constant writes — a naive dump can catch half of a transaction.

01

Create the /home/fivem/scripts/backup-db.sh script:

sudo -u fivem mkdir -p /home/fivem/scripts
sudo -u fivem nano /home/fivem/scripts/backup-db.sh

Paste the contents:

#!/bin/bash
set -euo pipefail

DB_NAME="fivem_framework"
BACKUP_DIR="/var/backups/fivem/database"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
OUTPUT="${BACKUP_DIR}/${DB_NAME}-${TIMESTAMP}.sql.gz"
RETENTION_DAYS=14

mysqldump \
  --single-transaction \
  --quick \
  --routines \
  --triggers \
  --events \
  --default-character-set=utf8mb4 \
  "${DB_NAME}" | gzip -9 > "${OUTPUT}"

find "${BACKUP_DIR}" -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete

echo "[$(date)] Backup OK: ${OUTPUT} ($(du -h "${OUTPUT}" | cut -f1))"

Replace fivem_framework with the real name of your database. The --single-transaction and --quick flags are what make the dump safe with a server in production: the first guarantees InnoDB consistency without locking, the second avoids loading the entire table into RAM.

02

Give it execute permission and run it once manually to validate:

sudo chmod +x /home/fivem/scripts/backup-db.sh
sudo -u fivem /home/fivem/scripts/backup-db.sh

You should see a line like Backup OK: /var/backups/fivem/database/fivem_framework-20260529-143022.sql.gz (87M). If an “access denied” error shows up, review ~/.my.cnf and the grants from the previous step.

Restore tests are mandatory

A backup that has never been restored isn’t a backup, it’s a file. Before trusting this routine, create a test database, restore a dump into it, and inspect critical tables (users, inventories, positions).

Server Files Backup Script

The file side is simpler but has its own traps — including volatile directories like logs and cache inflates the backup with no real gain, and copying txData during runtime triggers “file changed as we read it” warnings.

01

Create /home/fivem/scripts/backup-files.sh:

sudo -u fivem nano /home/fivem/scripts/backup-files.sh

Contents:

#!/bin/bash
set -euo pipefail

SOURCE_DIR="/home/fivem/server-data"
BACKUP_DIR="/var/backups/fivem/files"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
OUTPUT="${BACKUP_DIR}/fivem-files-${TIMESTAMP}.tar.gz"
RETENTION_DAYS=30

tar \
  --exclude='*/cache' \
  --exclude='*/logs' \
  --exclude='*/tmp' \
  --exclude='*.log' \
  --warning=no-file-changed \
  -czf "${OUTPUT}" \
  -C "$(dirname "${SOURCE_DIR}")" \
  "$(basename "${SOURCE_DIR}")"

find "${BACKUP_DIR}" -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete

echo "[$(date)] Backup OK: ${OUTPUT} ($(du -h "${OUTPUT}" | cut -f1))"

Adjust SOURCE_DIR to the real path where your server.cfg and resources folder live. The --warning=no-file-changed flag silences the noise from files modified during reading — expected behavior on an active server.

02

Permission and test:

sudo chmod +x /home/fivem/scripts/backup-files.sh
sudo -u fivem /home/fivem/scripts/backup-files.sh

For a server with 4 GB of resources, expect somewhere between 1 GB and 2 GB in the final archive (default gzip level).

Incremental backups for large volumes

If your resources go beyond 20 GB, consider restic or borgbackup instead of tar. Both do block-level deduplication — a daily backup only stores the delta, not the whole archive. Trade-off: slower restore and an extra tool in your stack.

Scheduling via cron

With both scripts validated manually, we schedule them to run automatically. The rule is simple: database with high frequency (daily), files with lower frequency (weekly), always during low-traffic hours.

01

Open the crontab for the fivem user:

sudo -u fivem crontab -e

Add:

# Database backup — every day at 04:30
30 4 * * * /home/fivem/scripts/backup-db.sh >> /var/log/fivem-backup.log 2>&1

# File backup — every Monday at 05:00
0 5 * * 1 /home/fivem/scripts/backup-files.sh >> /var/log/fivem-backup.log 2>&1

Create the log file and fix ownership to avoid a permission error on the first run:

sudo touch /var/log/fivem-backup.log
sudo chown fivem:fivem /var/log/fivem-backup.log
02

Confirm cron registered the entries:

sudo -u fivem crontab -l

The suggested times (04:30 and 05:00) tend to be the quietest hours for most servers. Adjust to whatever the inverse peak of your server is.

Verification

After 24 hours, validate that everything is running as expected.

ls -lh /var/backups/fivem/database/
ls -lh /var/backups/fivem/files/
tail -n 20 /var/log/fivem-backup.log

You should see at least one fresh .sql.gz in the database directory and success lines in the log. If the database backup is below 1 KB, something failed silently — open the .sql.gz with zcat file.sql.gz | head -50 and check that an actual dump shows up.

To test the restore, create an empty database and import a dump:

mysql -u root -p -e "CREATE DATABASE fivem_test;"
zcat /var/backups/fivem/database/fivem_framework-LATEST.sql.gz | mysql -u root -p fivem_test
mysql -u root -p fivem_test -e "SHOW TABLES;"

The table list should match the production server.

Troubleshooting

”mysqldump: Got error: 1044: Access denied”

The backup user is missing privileges. Re-run the GRANT statements from the user-creation step and confirm with SHOW GRANTS FOR 'fivem_backup'@'localhost';.

”tar: file changed as we read it” in a loop

Expected on an active server. The --warning=no-file-changed flag in the script already silences it. If it still shows up, an older tar version doesn’t support the flag — upgrade to tar >= 1.30.

Backup grows indefinitely

The find -mtime +N -delete only works if cron has been running for at least N+1 days. Check ls -lh in the directory and force a manual cleanup if needed: find /var/backups/fivem/database -name "*.sql.gz" -mtime +14 -delete.

Next Steps

  • Ship backups to off-site storage with rclone (S3-compatible, Backblaze B2, Google Drive) — a local backup doesn’t protect against losing the whole server
  • Configure a Discord webhook alert when the script fails, reading the cron exit code
  • Add dump size monitoring — alert if today’s file is 50% smaller than the weekly average, a sign of silent corruption
  • Document the restore procedure in a RUNBOOK.md file on the server itself — in an emergency, nobody wants to re-learn commands

If you’re putting this into production and want infrastructure tuned for FiveM servers, Hostini’s game hosting plans come with network-level DDoS protection and hypervisor snapshots — two extra layers that complement the backup routine described here.

Frequently asked questions

Can I run mysqldump while the FiveM server is online?

Yes, as long as you use the `--single-transaction` flag on InnoDB tables. It creates a consistent transaction without blocking writes, which is essential on a server with players connected. For MyISAM tables, consider `--lock-tables` or stop the server for a few seconds.

How much space will the backup take?

A typical FiveM server has between 2 GB and 10 GB of resources, and a gzipped database dump usually stays under 200 MB for databases with 5,000 players. Keep at least 3x the server size free on disk for rotation.

Do I need to stop the server to back up resources?

Not strictly, but tar reading directories being written in real time (logs, txData/data) can produce warnings. For production, schedule the backup during low-traffic windows and exclude volatile directories with `--exclude` on tar.

How do I restore only the database without touching server files?

Decompress the specific `.sql.gz` with `gunzip` and run `mysql -u user -p database < dump.sql`. Before that, take a dump of the current state as a safety net. The restore can take from seconds to minutes depending on database size.

Is it worth shipping backups to off-site storage?

Yes, always. A backup on the same disk as the server doesn't protect against hardware failure or host compromise. Use rclone with an S3-compatible service, Backblaze B2, or a secondary server via rsync over SSH.

How often should I run backups?

For the database, daily is recommended on active servers — maximum 24 hours of progress lost. For resources and configurations, weekly covers most cases since they change less often. Servers running an in-game economy may need database backups every 6 hours.

Topics:
Next steps VPS, dedicated or managed panel for FiveM, SAMP, MTA, Tibia and more.Host your game server with Hostini →
Was this tutorial helpful?
Chat on WhatsApp