Snapshots feel like backups. They aren't, and the difference only becomes obvious at the worst possible moment — when the VPS node itself has a problem and takes every snapshot down with it. If your entire backup strategy lives on the same physical storage as your live server, you don't have a backup strategy. You have a false sense of security. This is how to fix that with a script, a cron job, and a bucket that lives nowhere near your VPS.

Symptom: "We Have Backups" That Turn Out to Be Useless

This usually surfaces during an actual disaster, which is the worst time to find out. A client's VPS gets compromised, or a data center has an incident, and when it's time to restore, the "backup" turns out to be a snapshot on the same storage cluster, or a JetBackup archive sitting in /home/backups on the very disk that just died. Nothing survived because nothing ever left the server.

The industry shorthand for this is the 3-2-1 rule: three copies of your data, on two different types of storage, with one copy offsite. A snapshot and a local tarball both count as "on the server." Neither counts as offsite. You need at least one copy that would survive your VPS provider's entire data center burning down.

Cause: No One Ever Automated the Offsite Part

This isn't usually negligence — it's that manual backups don't scale. Someone sets up a one-time backup during initial VPS setup, feels good about it, and never touches it again. Six months later the site has three times the content, the manual backup is stale, and nobody remembers the last time it ran. Cron doesn't get tired or forget. A script does.

Fix: Build a Script, Schedule It, Ship It Offsite

The pattern is the same whether you're running a single WordPress site or a handful of apps on one VPS: dump the database, archive the files, encrypt if needed, push the result somewhere that isn't this server, then delete backups older than your retention window.

Step 1 — Write the Backup Script

Create /root/scripts/backup.sh on your VPS (adjust paths for your setup, and don't forget the bash shebang line as the very first line of the file):

set -euo pipefail

DATE=$(date +%F)
BACKUP_DIR="/root/backups/$DATE"
SITE_DIR="/var/www/example.com"
DB_NAME="example_db"
DB_USER="example_user"
DB_PASS="your_db_password"

mkdir -p "$BACKUP_DIR"

# Dump the database
mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" | gzip > "$BACKUP_DIR/db.sql.gz"

# Archive site files, excluding cache junk
tar --exclude='*/wp-content/cache/*' -czf "$BACKUP_DIR/files.tar.gz" "$SITE_DIR"

echo "Local backup complete: $BACKUP_DIR"

Make it executable with chmod +x /root/scripts/backup.sh and run it once by hand before you trust cron with it. If it fails silently in a cron job at 2 a.m., you won't notice for weeks.

Step 2 — Send It Offsite with Rclone

Rsync alone only gets your backup to another folder or another server you control. For true offsite storage, rclone talking to S3, Backblaze B2, or Wasabi is the easiest path — cheap, and completely outside your hosting provider's blast radius.

Install and configure it once with rclone config (pick S3-compatible storage, paste in your access key and secret), then add this to the bottom of the script:

rclone sync "$BACKUP_DIR" remote:my-backups-bucket/$DATE --log-file=/var/log/rclone-backup.log

# Keep only local copies from the last 3 days
find /root/backups/* -maxdepth 0 -mtime +3 -print0 | xargs -0 rm -r

If you'd rather push to a second VPS or a home NAS instead of cloud storage, swap the rclone sync line for plain rsync -avz -e ssh "$BACKUP_DIR/" user@remote-host:/backups/$DATE/. Either way, the point is the same: the data has to leave this machine.

Step 3 — Schedule It with Cron

Open the root crontab with crontab -e and add a nightly run at 2 AM:

0 2 * * * /root/scripts/backup.sh >> /var/log/backup.log 2>&1

Redirecting output to a log file is not optional. Without it, a script that starts failing every night just fails quietly forever, and you find out during the next actual emergency.

Step 4 — Rotate Remote Copies Too

Local retention is easy to forget about on the remote end. Most S3-compatible providers support lifecycle rules directly in the bucket settings — set one to delete objects older than 30 or 90 days, whatever your retention policy needs. That way storage costs stay flat even as your backup history grows, and you're not manually pruning a bucket by hand every quarter.

Step 5 — Actually Test the Restore

This is the step almost everyone skips, and it's the one that matters most. A backup you've never restored is a theory, not a backup. Once a month, spin up a cheap test VPS or a local Docker container, pull down the latest backup, and walk through a full restore:

  • Download and extract files.tar.gz into a test web root
  • Import db.sql.gz into a fresh MySQL instance
  • Load the site and click through a few pages, an admin login, a form submission

If any part of that fails, you want to find out now, on a test box, not during a real recovery with a client watching the clock.

Prevention: Monitor the Backup Job Like Any Other Service

A cron job that fails silently is worse than no backup at all, because it lies to you about being safe. Add a lightweight check on top of the script:

  • Use a dead man's switch service (ping a URL at the end of a successful run; get alerted if the ping doesn't arrive)
  • Have the script email you only on failure, using || mail -s "Backup FAILED on $(hostname)" you@example.com appended after the critical commands
  • Check the bucket size periodically — a backup that's suspiciously small or hasn't grown in weeks is a red flag before it's a crisis

Snapshot, cPanel Backup, or Cron+Rclone? Use All Three, for Different Jobs

MethodSpeed to restoreSurvives node failureBest for
VPS SnapshotMinutesNoRolling back a risky change in the next hour
cPanel/JetBackupFast, GUI-drivenOnly if configured to push offsiteShared/cPanel hosting, non-technical restores
Cron + rsync/rcloneSlower, manual stepsYes, by designRoot-access VPS, disaster recovery, compliance retention

None of these replace the others. A snapshot saves you an hour of downtime after a bad update. Offsite cron backups save the business when the entire server is gone.

Frequently Asked Questions

How often should a VPS back up?

Nightly is the standard baseline for most sites. If your database changes constantly — an active e-commerce store, a forum, a booking system — consider a lighter database-only dump every few hours on top of the nightly full backup.

Is rsync enough on its own, without rclone?

Rsync works fine if the destination is a server or storage box you control over SSH. It has no native support for S3-style object storage, which is why rclone (or a provider's own CLI tool) is the simpler route when the destination is cloud storage rather than another machine.

Should backups be encrypted before they leave the VPS?

Yes, if they contain customer data, payment details, or anything regulated. Pipe the tar output through gpg --symmetric before the rclone sync step, and store the passphrase somewhere other than the server itself.

What's a reasonable retention period?

A common pattern is 7 daily backups, 4 weekly, and 3-6 monthly — enough to recover from a slow-burning problem you didn't notice for a couple of weeks, without the storage bill growing forever.

Can SkyServer VPS customers get help setting this up?

Yes — open a ticket from your client area and our support team can help you configure the script, cron schedule, and offsite destination for your specific setup, or point you to a managed backup add-on if you'd rather not maintain the script yourself.