
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
- One tool, many providers — learn one set of commands
- Built-in encryption — the
cryptbackend encrypts before uploading - Bandwidth limits — keep rclone from saturating your link during business hours
- Resume support — picks up where it left off after a dropped connection
- Filters — send only what you want (
--exclude *.log)
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:
- Choose
nfor new remote - Name:
s3backup - Storage:
4(Amazon S3 compliant) - Provider:
AWS(orWasabi,Backblaze) - access_key_id / secret_access_key: paste your AWS credentials
- Region:
ap-southeast-1(Singapore) - Endpoint: leave blank for AWS
- 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
| Command | What 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: /mnt | Mount the cloud as a folder |
3-2-1 Backup Strategy Checklist
- 3 copies — original + local backup + cloud backup
- 2 media — disk + cloud (different types)
- 1 off-site — at least one copy outside the building (this is where rclone helps)
- Encrypt with a crypt remote — the provider sees no plaintext
- Set retention — purge backups older than X days automatically
- 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