BACKUPS
June 24, 2026

How to Automate Server Backups (and Actually Test Restores)

11 min read
Author
CloudStick Team
Server Infrastructure
Share this article
Automate Server Backups
CloudStick
Automate & Test Backups

Why Testing Backups Is the Part Everyone Skips

A backup you have never restored is not a backup — it is a guess. Drives fail silently, backup scripts write corrupt archives, cron jobs stop running after a system update, and rsync destination directories fill up unnoticed. None of these failures show up in a monitoring dashboard unless you specifically look for them. The only way to know a backup works is to restore it to a test environment and verify the result.

This guide covers both sides: setting up automated backups that actually run reliably, and building a restore-testing routine that catches failures before they cost you anything.

What to Back Up on a Web Server

A complete server backup covers four categories of data:

  • Website files — everything under /var/www or your web root. For WordPress sites, this includes core, themes, plugins, and wp-content/uploads.
  • Databases — MySQL or MariaDB databases exported with mysqldump. This is the most critical data — files without a matching database are useless.
  • Configuration files/etc/nginx, /etc/php, ~/.ssh, any custom scripts under /etc or /usr/local.
  • Mail data — if you run email on the server, /var/mail and Postfix/Dovecot configs.
WARNING

Never store backup files on the same server being backed up. If the server is compromised or the disk fails, backups stored locally are lost with the primary data. Always transfer to a separate location — a different server, object storage (S3, Wasabi, B2), or a remote NFS/SFTP destination.

Setting Up Automated Backups

A reliable backup script handles database export, file archiving, compression, offsite transfer, and cleanup of old backups in one run:

#!/bin/bash
DATE=$(date +%Y-%m-%d)
BACKUP_DIR="/var/backups/daily/$DATE"
DB_USER="backup_user"
DB_PASS="your_password"
S3_BUCKET="s3://your-backup-bucket"
mkdir -p "$BACKUP_DIR"
# Export all databases
mysqldump --user="$DB_USER" --password="$DB_PASS" \
--all-databases --single-transaction \
| gzip > "$BACKUP_DIR/all-databases.sql.gz"
# Archive web files
tar -czf "$BACKUP_DIR/www.tar.gz" /var/www
# Sync to S3 (requires aws-cli configured)
aws s3 sync "$BACKUP_DIR" "$S3_BUCKET/$DATE/"
# Delete local backups older than 7 days
find /var/backups/daily -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +
echo "Backup completed: $DATE" | mail -s "Backup OK" admin@example.com

Save this as /usr/local/bin/run-backup.sh and make it executable with chmod +x /usr/local/bin/run-backup.sh. Then schedule it with cron:

# Run backup at 2am daily
0 2 * * * root /usr/local/bin/run-backup.sh >> /var/log/backup.log 2>&1

Testing Restores: The Part That Actually Matters

Schedule a restore test monthly at minimum. The process: spin up a fresh VPS (or use a local VM), restore your latest backup, and verify the site functions. This validates both the backup content and your restore procedure.

# 1. Download from S3
aws s3 sync s3://your-backup-bucket/2026-06-24/ /tmp/restore-test/
# 2. Restore the database
gunzip -c /tmp/restore-test/all-databases.sql.gz | mysql -u root -p
# 3. Restore web files to a test path
tar -xzf /tmp/restore-test/www.tar.gz -C /tmp/restore-test/
# 4. Verify expected files exist
ls /tmp/restore-test/var/www/html/wp-config.php
mysql -u root -p -e "SHOW DATABASES;"
TIP

Document your restore procedure as a numbered runbook — not just the commands, but the expected output at each step. When you actually need to restore under pressure at 3am, you want step-by-step instructions, not commands you have to remember. Reviewing this runbook is itself a useful part of the monthly test.

Monitoring Backup Success and Failure

A backup script that runs silently is dangerous — you have no idea if it succeeded. At minimum, the script should send a success or failure email. A better approach is to integrate with a dead-man's switch monitoring service like Healthchecks.io: your backup script pings a URL on success, and the service pages you if it does not hear from the script within the expected window.

# Add at end of backup script on success
curl -fsS --retry 3 https://hc-ping.com/your-uuid > /dev/null

Also monitor the backup destination size. Add a check to alert you if the total size of recent backups shrinks unexpectedly — this can indicate the backup script stopped writing new files while cron continued to report success.

CloudStick Handles Backup Scheduling and Storage

CloudStick's Backups section automates all of the above — website files and databases are backed up on a configurable schedule, and stored in CloudStick's managed backup storage (included on all paid plans, starting at 4 GB on Basic). The Archived Backups view shows every snapshot with its date, size, and restore status, and you can download any backup file directly to your local machine to run your own restore test.

See the CloudStick knowledge base: How to Enable Free Backup Quota for step-by-step instructions on activating backup storage and configuring your first automated backup schedule from the dashboard.

Leave a comment
Full Name
Email Address
Message
Contents

We use cookies to improve your experience

CloudStick uses cookies to personalise content, analyse traffic and keep you signed in. Cookie Policy · Terms of Service

Manage cookies