Install rclone
sudo dnf install rclone -y
Configure Cloudflare R2 (Recommended)
Cloudflare R2 has no egress fees — you pay only for storage, not downloads. The free tier (10GB) covers most personal backup needs.
In Cloudflare dashboard:
- R2 Object Storage → Create bucket → name it
wp-backups - Manage R2 API Tokens → Create API Token with Object Read & Write permissions
- Note the Access Key ID, Secret Access Key, and the endpoint URL (format:
https://ACCOUNT_ID.r2.cloudflarestorage.com)
Configure rclone:
rclone config
Follow the prompts:
n (new remote)
Name: r2
Storage type: s3
Provider: Cloudflare
Access Key ID: [your key]
Secret Access Key: [your secret]
Endpoint: https://ACCOUNT_ID.r2.cloudflarestorage.com
Leave other settings as default
Test the connection:
rclone ls r2:wp-backups
# Should return empty list (bucket exists but is empty)
Configure Google Drive (Alternative)
Google Drive is simpler to set up and free up to 15GB:
rclone config
n (new remote)
Name: gdrive
Storage type: drive (Google Drive)
rclone will open a browser for OAuth authentication. Follow the prompts. After authentication, create a backup folder:
rclone mkdir gdrive:wp-backups
Create the Files Backup Script
sudo nano /usr/local/bin/wp-files-backup.sh
#!/bin/bash
# WordPress Files Backup — uploads to cloud storage with rclone
# Backs up: database backups directory + wp-content/uploads
REMOTE="r2:wp-backups" # Change to gdrive:wp-backups for Google Drive
LOG="/var/log/wp-backup.log"
DATE=$(date +%Y-%m-%d)
echo "$(date): Starting files backup" >> $LOG
# Upload database backups offsite
rclone sync /var/backups/wordpress/db/ \
${REMOTE}/db/ \
--log-file=$LOG \
--log-level INFO
# Upload wp-content/uploads for each site
# Add one line per WordPress site
rclone sync /var/www/yourdomain.com/wp-content/uploads/ \
${REMOTE}/uploads/yourdomain.com/ \
--log-file=$LOG \
--log-level INFO
echo "$(date): Files backup complete" >> $LOG
Make executable:
sudo chmod +x /usr/local/bin/wp-files-backup.sh
Test Manually First
sudo /usr/local/bin/wp-files-backup.sh
Check the log:
tail -20 /var/log/wp-backup.log
Verify files appeared in cloud storage:
# For R2
rclone ls r2:wp-backups/db/
# For Google Drive
rclone ls gdrive:wp-backups/db/
Add to Cron
sudo crontab -e
The complete backup cron schedule:
# Daily database backup at 2:00 AM
0 2 * * * /usr/local/bin/wp-db-backup.sh
# Daily offsite sync at 3:00 AM (after DB backup completes)
0 3 * * * /usr/local/bin/wp-files-backup.sh
The one-hour gap ensures the database backup finishes before the sync tries to upload it.
Monitor Backup Health
# Check recent backup activity
tail -50 /var/log/wp-backup.log
# Verify latest DB backup exists and is recent
ls -lt /var/backups/wordpress/db/ | head -5
# Check remote storage size
rclone size r2:wp-backups
Check this once a week. If the log shows errors or the most recent backup is more than 24 hours old, something needs attention.