Automatic Backups on a Linux Server With Cron and Bash Scripts

Automatic Backups on a Linux Server With Cron and Bash Scripts

Build a real backup routine on a Linux VDS: bash scripts, database dumps, incremental rsync, cron scheduling, offsite copies and restore verification.

White Bilişim

Automatic Backups on a Linux Server

Data loss is the risk that ends projects. Hardware failures, software bugs and plain human error all threaten your data, and the only defence that works reliably is an automated backup system you never have to remember. This guide covers building one on a Linux VDS.

Backup Strategy

The 3-2-1 Rule

The industry standard is worth following:

  • 3 copies: the original plus two backups
  • 2 different media: local disk plus a remote server
  • 1 copy offsite: in a different physical location

💡 White Bilişim includes free daily automatic backups on every VDS plan. We still recommend running your own backup routine on top of that, because a backup you control is a backup you can test.

Method 1: A Simple Bash Script

Basic Backup Script

#!/bin/bash
# backup.sh - basic backup script
 
# Settings
BACKUP_DIR="/backup"
SOURCE_DIRS="/var/www /etc /home"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/backup_$DATE.tar.gz"
LOG_FILE="$BACKUP_DIR/backup.log"
RETENTION_DAYS=7
 
# Create the backup directory
mkdir -p $BACKUP_DIR
 
# Start the backup
echo "[$DATE] Backup started..." >> $LOG_FILE
 
tar -czf $BACKUP_FILE $SOURCE_DIRS 2>> $LOG_FILE
 
if [ $? -eq 0 ]; then
    FILESIZE=$(du -h $BACKUP_FILE | cut -f1)
    echo "[$DATE] Backup succeeded: $BACKUP_FILE ($FILESIZE)" >> $LOG_FILE
else
    echo "[$DATE] ERROR: backup failed!" >> $LOG_FILE
fi
 
# Clean up old backups
find $BACKUP_DIR -name "backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "[$DATE] Backups older than $RETENTION_DAYS days removed." >> $LOG_FILE
# Make the script executable
chmod +x /root/backup.sh
 
# Test it
./backup.sh

Method 2: Database Backups

MySQL and MariaDB

#!/bin/bash
# db_backup.sh - database backup
 
BACKUP_DIR="/backup/db"
DATE=$(date +%Y%m%d_%H%M%S)
DB_USER="root"
DB_PASS="database_password"
 
mkdir -p $BACKUP_DIR
 
# Dump every database
mysqldump -u$DB_USER -p$DB_PASS --all-databases --single-transaction | gzip > "$BACKUP_DIR/all_db_$DATE.sql.gz"
 
# Dump a single database
mysqldump -u$DB_USER -p$DB_PASS fivem_db --single-transaction | gzip > "$BACKUP_DIR/fivem_db_$DATE.sql.gz"
 
# Remove dumps older than 14 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +14 -delete

PostgreSQL

#!/bin/bash
# pg_backup.sh
BACKUP_DIR="/backup/pgsql"
DATE=$(date +%Y%m%d_%H%M%S)
 
mkdir -p $BACKUP_DIR
 
# Dump every database
sudo -u postgres pg_dumpall | gzip > "$BACKUP_DIR/pg_all_$DATE.sql.gz"

Method 3: Incremental Backups With rsync

rsync only copies what changed, which makes frequent backups cheap:

#!/bin/bash
# rsync_backup.sh - incremental backup
 
SOURCE="/var/www"
DEST="/backup/rsync"
LOG="/var/log/rsync_backup.log"
 
mkdir -p $DEST
 
rsync -avz --delete \
    --exclude='*.log' \
    --exclude='node_modules/' \
    --exclude='.git/' \
    $SOURCE $DEST \
    >> $LOG 2>&1
 
echo "[$(date)] rsync backup finished." >> $LOG

Sending Backups to a Remote Server

# Push backups to another server
rsync -avz -e "ssh -p 22" /backup/ backup_user@REMOTE_SERVER_IP:/remote-backup/

Scheduling With Cron

Cron Syntax

# ┌───────── Minute (0-59)
# │ ┌─────── Hour (0-23)
# │ │ ┌───── Day of month (1-31)
# │ │ │ ┌─── Month (1-12)
# │ │ │ │ ┌─ Day of week (0-7, 0 and 7 are Sunday)
# │ │ │ │ │
# * * * * * command

Adding Cron Jobs

# Open the cron editor
crontab -e
 
# Full backup every night at 03:00
0 3 * * * /root/backup.sh
 
# Database backup every 6 hours
0 */6 * * * /root/db_backup.sh
 
# rsync every hour
0 * * * * /root/rsync_backup.sh
 
# Weekly full backup every Sunday at 02:00
0 2 * * 0 /root/weekly_backup.sh

Listing Cron Jobs

# Show the current user's cron jobs
crontab -l
 
# Show root's cron jobs
sudo crontab -l

Verifying Your Backups

An untested backup is a guess. Check them on a schedule:

# List the backup files
ls -lh /backup/
 
# Verify the integrity of a tar archive
tar -tzf /backup/backup_20260408_030000.tar.gz > /dev/null && echo "Backup is intact" || echo "Backup is corrupt!"
 
# Test a database dump by restoring it into a scratch database
zcat /backup/db/all_db_20260408.sql.gz | mysql -u root -p test_restore_db

Email Notifications

#!/bin/bash
# backup_with_notification.sh
 
# Run the backup
/root/backup.sh
 
# Report the result by email
if [ $? -eq 0 ]; then
    echo "Backup succeeded - $(date)" | mail -s "✅ Server backup succeeded" admin@yoursite.com
else
    echo "ERROR: backup failed! - $(date)" | mail -s "❌ Server backup FAILED" admin@yoursite.com
fi

Game Server Backup Examples

Backing Up a FiveM Server

#!/bin/bash
# fivem_backup.sh
FIVEM_DIR="/home/fivem-server"
BACKUP_DIR="/backup/fivem"
DATE=$(date +%Y%m%d_%H%M%S)
 
mkdir -p $BACKUP_DIR
 
# Back up the database
mysqldump -u root -p fivem_db | gzip > "$BACKUP_DIR/fivem_db_$DATE.sql.gz"
 
# Back up the server files
tar -czf "$BACKUP_DIR/fivem_files_$DATE.tar.gz" \
    $FIVEM_DIR/server.cfg \
    $FIVEM_DIR/resources/ \
    --exclude="$FIVEM_DIR/resources/[system]"
 
find $BACKUP_DIR -mtime +7 -delete

Backing Up a Minecraft World

#!/bin/bash
# minecraft_backup.sh
MC_DIR="/home/minecraft"
BACKUP_DIR="/backup/minecraft"
DATE=$(date +%Y%m%d_%H%M%S)
 
mkdir -p $BACKUP_DIR
 
# Back up the world
tar -czf "$BACKUP_DIR/world_$DATE.tar.gz" $MC_DIR/world/
 
find $BACKUP_DIR -name "world_*.tar.gz" -mtime +14 -delete

Which Plan for Backup Workloads

NeedRecommended planSpecs
Simple backupsENT-22 Core, 4 GB RAM, 40 GB SSD
Frequent backupsENT-58 Core, 10 GB RAM, 100 GB SSD
Large data setsPRO-48 Core Ryzen, 10 GB RAM, 100 GB SSD

Conclusion

Automated backups are the single most important habit in server administration. Cron jobs and a few short scripts remove the human element entirely. We include free daily backups on every VDS plan, but building your own routine on top of that is still strongly recommended.

👉 To keep backups on separate hardware, see our backup server plans, and Xeon Enterprise VDS or Ryzen Premium VDS for the production side.