Automating server backups with scripts and cron

Step-by-step guide to automated server backup with Bash script and cron; including file and MySQL backup, version rotation, and secure transfer to external storage.

6 min Updated 23 Aug 2026

Why Automated Server Backup Is No Longer an Option?

Every server administrator has experienced data loss at least once; accidental file deletion, disk failure, or a ransomware attack. In such moments, the only thing that saves you is a fresh and recoverable backup. But with manual backup, a simple human error can delay it forever. The standard solution is implementing automated server backup by combining scripting and cron jobs; a system that runs on a defined schedule without your intervention and gives you peace of mind about your data.

In this article, we provide a practical and complete solution for automated server backup: from writing a backup script for files and MySQL database to rotating old versions and securely transferring backups to external storage. All examples have been tested on Ubuntu/Debian, but they also work on other Linux distributions with minor changes.

Prerequisites and Folder Structure

Before writing the script, we need to prepare the environment. We assume your server runs a web application with static files and a MySQL/MariaDB database. First, create the required folders:

sudo mkdir -p /opt/backup-scripts
sudo mkdir -p /var/backups/local
sudo mkdir -p /var/backups/logs
  • /opt/backup-scripts is where backup scripts are stored.
  • /var/backups/local temporarily stores the generated backups.
  • /var/backups/logs is used to record script execution reports.

Also, make sure the following tools are installed:

sudo apt update
sudo apt install mysql-client rsync gzip

Writing the Automated Server Backup Script

Our script performs three main tasks: file backup, database backup, and deleting old versions. Create the script file with your preferred editor:

sudo nano /opt/backup-scripts/backup.sh

Place the following content in it:

#!/bin/bash
# ============================================
# Automated server backup - files and database
# ============================================

# Settings
BACKUP_DIR="/var/backups/local"
LOG_DIR="/var/backups/logs"
DATE=$(date +%Y-%m-%d_%H-%M-%S)
RETENTION_DAYS=7

# Site files path (example)
SITE_DIR="/var/www/mysite"
DB_NAME="mydb"
DB_USER="backup_user"
DB_PASS="S3cure_P@ssw0rd"

# Log file
LOG_FILE="$LOG_DIR/backup_$DATE.log"

# Start
echo "Backup started at $(date)" > "$LOG_FILE"

# 1) File backup with tar
echo "Backing up files..." >> "$LOG_FILE"
tar -czf "$BACKUP_DIR/files_$DATE.tar.gz" -C "$SITE_DIR" . 2>> "$LOG_FILE"

# 2) Database backup with mysqldump
echo "Backing up database..." >> "$LOG_FILE"
mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" | gzip > "$BACKUP_DIR/db_$DATE.sql.gz" 2>> "$LOG_FILE"

# 3) Delete old backups (version rotation)
echo "Cleaning old backups..." >> "$LOG_FILE"
find "$BACKUP_DIR" -name "files_*.tar.gz" -mtime +$RETENTION_DAYS -delete >> "$LOG_FILE" 2>&1
find "$BACKUP_DIR" -name "db_*.sql.gz" -mtime +$RETENTION_DAYS -delete >> "$LOG_FILE" 2>&1

# End
echo "Backup completed at $(date)" >> "$LOG_FILE"

Then make the script executable:

sudo chmod +x /opt/backup-scripts/backup.sh

Explanation of Key Script Sections

  • DATE variable: Creates backup filenames with the exact date and time so versions don't conflict with each other.
  • File backup: Uses the tar command to compress the entire site folder. Using -C prevents absolute paths from being stored in the backup, making restoration simpler.
  • Database backup: Uses mysqldump to take a logical dump of the database and immediately compresses it with gzip. This significantly reduces the final file size.
  • Version rotation: The find command locates and deletes files older than 7 days to prevent the disk from filling up.
Common mistake: Putting the database password in plain text in the script is a serious security risk. If an unauthorized user reads the script, the database information is exposed. A better solution is to use the ~/.my.cnf file with restricted access:
chmod 600 ~/.my.cnf
Then in the script, only use mysqldump "$DB_NAME" without specifying the user and password.

Transferring Backups to External Storage

Storing backups on the same server is useless against disk failures or ransomware attacks. The best practice is to automatically transfer backups to an external storage space. We'll examine two common methods.

Transferring with rsync to Another Server

If you have a separate backup server, rsync is the best option. First, set up the SSH key so the script works without requiring a password:

ssh-keygen -t rsa -b 4096
ssh-copy-id backup_user@backup-server.example.com

Then add this line to the end of the script:

rsync -avz --remove-source-files "$BACKUP_DIR/" backup_user@backup-server.example.com:/backups/ >> "$LOG_FILE" 2>&1

The --remove-source-files option deletes local files after a successful transfer, keeping the main server's disk space free.

Transferring with rclone to Cloud Storage

For transferring to cloud services like Google Drive or S3, the rclone tool is very popular. Installation and setup:

sudo apt install rclone
rclone config

After configuring the remote, add the following line to the script:

rclone copy "$BACKUP_DIR" remote:backups/ --log-file="$LOG_FILE"

Setting Up a Cron Job for Automatic Execution

Now it's time for scheduling. Open the cron file with crontab -e and add the following line to run the script every night at 2 AM:

0 2 * * * /opt/backup-scripts/backup.sh

Use this pattern for daily execution at a specific time. If you need a backup every 6 hours:

0 */6 * * * /opt/backup-scripts/backup.sh

Testing the Cron Job

After setting up cron, make sure to test that the script runs correctly. First, run it manually:

sudo /opt/backup-scripts/backup.sh

Then check the log output:

cat /var/backups/logs/backup_*.log

If there are any errors, fix them. To ensure cron is working, you can add a temporary line to crontab that runs every minute and creates a test file:

* * * * * touch /tmp/cron-test

After one minute, if the /tmp/cron-test file is created, cron is working correctly.

Troubleshooting tip: If cron isn't running, you've likely written the absolute path of the script incorrectly or the script isn't executable. Also, remember that cron has a limited environment; if your script needs specific environment variables, define them inside the script itself.

Backup Restoration; The Forgotten Part

A backup that has never been restored is practically worthless. At least once a month, perform the restoration process in a test environment. To restore files:

tar -xzf files_2025-01-15_02-00-01.tar.gz -C /tmp/restore-test/

And for the database:

gunzip < db_2025-01-15_02-00-01.sql.gz | mysql -u root -p mydb

This simple test can determine the difference between a real crisis and a minor incident.

Improving Backup Script Security

A few simple measures can significantly enhance the security of your automated server backup:

  • Encrypting backups: You can encrypt backup files before transfer using the gpg tool:
    gpg --symmetric --cipher-algo AES256 backup.tar.gz
  • Restricting access to the backup folder: Only the root user should have access to /var/backups:
    sudo chmod 700 /var/backups
  • Monitoring backup execution: Write a simple script that emails you if today's backup file wasn't created. You can use mailutils.

Conclusion

Implementing automated server backup with scripts and cron is one of the most important actions you can take for the stability of your service. In this article, we wrote a complete script for backing up files and databases, rotating old versions, and transferring to external storage. You can easily customize this solution to fit your needs; for example, adding backups of specific folders, using stronger compression, or sending reports to Telegram.

If you're looking for infrastructure that simplifies these processes, ServerNet's web hosting and cloud server services can be a suitable option; but the most important principle is to get started. Write your backup script today and set up cron; tomorrow, when something happens, you'll thank yourself.

Was this page helpful?