Automate VPS Backups with rclone to S3 / Google Drive

A backup stored on the same machine as production is not a real backup — if the server fails or gets compromised, the backup goes with it. The safest approach is to ship backups to off-host cloud storage.

rclone is "rsync for the cloud" — one tool for 70+ providers: S3, Google Drive, OneDrive, Backblaze B2, Dropbox, Wasabi, and more. This guide configures rclone on an Ubuntu VPS, writes a backup script, and schedules nightly uploads to S3 and Google Drive.

Prerequisites: An Ubuntu VPS with sudo access, plus a cloud storage account (S3 / B2 / Google Drive / OneDrive) to receive the backups.

Why rclone Instead of aws-cli or gsutil

Step 1 — Install rclone

Use the official installer — Ubuntu's package is often old:

sudo -v ; curl https://rclone.org/install.sh | sudo bash
rclone version

You should see 1.65 or newer.

Step 2 — Configure an S3 Remote

Start the wizard:

rclone config

Follow the prompts:

  1. Choose n for new remote
  2. Name: s3backup
  3. Storage: 4 (Amazon S3 compliant)
  4. Provider: AWS (or Wasabi, Backblaze)
  5. access_key_id / secret_access_key: paste your AWS credentials
  6. Region: ap-southeast-1 (Singapore)
  7. Endpoint: leave blank for AWS
  8. ACL: private

Test it:

rclone lsd s3backup:

Step 3 — Configure Google Drive

Google Drive needs OAuth. If your VPS has no browser, run the wizard on your laptop and copy the token to the VPS.

On your laptop:

rclone config

Pick Google Drive, leave client_id/secret blank, choose y to open a browser, sign in, and grant access.

The token lands in ~/.config/rclone/rclone.conf. Copy it to the VPS:

scp ~/.config/rclone/rclone.conf user@your-vps:/home/user/.config/rclone/rclone.conf

Step 4 — Encrypt Before Uploading (Recommended)

The crypt backend encrypts file names and contents before upload — the cloud provider sees only ciphertext.

rclone config

Choose n, name it backup_enc, type crypt, remote: s3backup:bucket-name/encrypted, set a password (record it!).

⚠️ Never lose the crypt password. rclone has no recovery. Store it in a password manager — and keep a backup of that.

Step 5 — Nightly Backup Script

Create /usr/local/bin/backup-daily.sh:

sudo nano /usr/local/bin/backup-daily.sh

Example contents (MySQL + web + cloud):

#!/bin/bash
set -e
DATE=$(date +%F-%H%M)
BACKUP_DIR=/tmp/backup_$DATE
mkdir -p $BACKUP_DIR

# 1. Dump MySQL
mysqldump --all-databases --single-transaction \
  -u backup -p'BackupPassword!' > $BACKUP_DIR/mysql_all.sql

# 2. Archive the web folder
tar -czf $BACKUP_DIR/www.tar.gz /var/www

# 3. Push to S3 (encrypted)
rclone copy $BACKUP_DIR backup_enc:daily/$DATE \
  --transfers=4 --checkers=8 \
  --bwlimit "08:00,2M 22:00,off" \
  --log-file=/var/log/rclone-backup.log

# 4. Delete cloud backups older than 30 days
rclone delete backup_enc:daily --min-age 30d --log-file=/var/log/rclone-backup.log

# 5. Clean local temp files
rm -rf $BACKUP_DIR

echo "Backup completed: $DATE" >> /var/log/rclone-backup.log

Make it executable:

sudo chmod +x /usr/local/bin/backup-daily.sh

Step 6 — Schedule via Cron at 3 AM

sudo crontab -e

Add:

0 3 * * * /usr/local/bin/backup-daily.sh >> /var/log/cron-backup.log 2>&1

Step 7 — Test the Restore

A backup you never restore is no backup. Pull a file down:

rclone copy backup_enc:daily/2026-05-15-0300/www.tar.gz /tmp/test_restore/
ls -la /tmp/test_restore/

Tip: Run a restore drill monthly — catches silently broken scripts before you need them.

Common rclone Commands

CommandWhat it does
rclone copy SRC REMOTE:Copy (does not delete at destination)
rclone sync SRC REMOTE:Mirror sync (deletes files missing from SRC)
rclone ls REMOTE:List all files
rclone lsd REMOTE:List directories only
rclone size REMOTE:Total size used
rclone check SRC REMOTE:Verify files match
rclone mount REMOTE: /mntMount the cloud as a folder

3-2-1 Backup Strategy Checklist

  1. 3 copies — original + local backup + cloud backup
  2. 2 media — disk + cloud (different types)
  3. 1 off-site — at least one copy outside the building (this is where rclone helps)
  4. Encrypt with a crypt remote — the provider sees no plaintext
  5. Set retention — purge backups older than X days automatically
  6. Test restores monthly — an unrestorable backup is not a backup

Comparing Cloud Storage Providers for VPS Backups

rclone supports dozens of providers, each with different pricing and performance characteristics. Choosing the right backend can substantially reduce your backup cost without sacrificing reliability.

Provider Storage cost Egress cost Best for
Amazon S3 Standard ~$0.023/GB/month $0.09/GB General use, high SLA needs
Backblaze B2 $0.006/GB/month $0.01/GB Budget-conscious, large backups
Wasabi $0.0069/GB/month Free Frequent restores, S3-compatible
Google Drive (15 GB free) Free 15 GB / $2.99/month 100 GB Free Small projects, zero extra cost
S3 Glacier Instant Retrieval $0.004/GB/month $0.03/GB Long-term archiving, rare restores

Adding Failure Notifications to Your Backup Script

A silent cron job is a dangerous cron job. If your backup script fails without alerting you, you may only discover the problem when you urgently need to restore — by which point weeks of backups could be missing. Here are two practical notification approaches:

Option 1: Webhook notification (Slack, Discord, Line Notify)

#!/bin/bash
# Add at the end of backup-daily.sh

WEBHOOK_URL="https://hooks.yourservice.com/abc123"
LOG="/var/log/rclone-backup.log"

if [ $? -eq 0 ]; then
  STATUS="Backup succeeded: $(date +%F)"
else
  STATUS="Backup FAILED: $(date +%F) — check $LOG"
fi

curl -s -X POST -H 'Content-type: application/json' \
  --data "{\"text\":\"$STATUS\"}" "$WEBHOOK_URL"

Option 2: healthchecks.io ping (free tier available)

The script pings a URL on each successful run. If the ping is not received within the expected window, the service sends you an email automatically:

# Add at the very end of your backup script
curl -fsS --retry 3 https://hc-ping.com/YOUR-UUID-HERE > /dev/null

rclone Filters — Send Only What You Need

Uploading every file on the server wastes storage and money. rclone's filter system lets you include or exclude paths with precise control. Create a filter file at /etc/rclone-backup.filter:

# Include
+ /var/www/**
+ /etc/nginx/**
+ /home/*/public_html/**
+ *.sql
+ *.sql.gz

# Exclude
- *.log
- *.tmp
- /tmp/**
- /var/cache/**
- node_modules/**
- .git/**
- __pycache__/**

Pass the filter file to rclone:

rclone copy /var/ backup_enc:daily/$DATE \
  --filter-from /etc/rclone-backup.filter \
  --transfers=4 \
  --log-file=/var/log/rclone-backup.log

Always do a dry run first to confirm what will be transferred without actually sending anything:

rclone copy --dry-run --filter-from /etc/rclone-backup.filter /var/ backup_enc:daily/test

Monitoring Backup Size and Storage Trends

Knowing how much space your backups consume helps you plan costs and detect anomalies — a sudden spike in backup size may indicate a runaway log file or database growth. Use these rclone commands to keep track:

# Total size of all backups
rclone size backup_enc:daily

# Size of a specific date's backup
rclone size backup_enc:daily/2026-06-01-0300

# List the 10 largest files across all backups
rclone ls backup_enc:daily | sort -rn | head -10

# Count files and total bytes in a human-readable summary
rclone about backup_enc:

Schedule a weekly summary report by adding a cron entry that writes rclone size backup_enc:daily output to a log file or sends it via webhook. Reviewing this report once a week takes less than two minutes and catches problems early.

Need a Reliable VPS for Backups?

AsiaGB VPS from 500 THB/month with SSD and generous bandwidth — perfect for shipping large backups to cloud storage automatically.

View VPS Plans