Automating Backups to a Remote Server with rsync
Automate backups to a remote server with rsync: step-by-step, secure SSH setup and simple commands. A beginner-friendly Linux/DevOps guide to schedule reliable, efficient backups.
Short introduction
Automating backups to a remote server with rsync gives you a fast, efficient way to keep copies of important data offsite. This tutorial walks through why rsync is a great choice, how to set up passwordless SSH, write reliable rsync commands (with a commands table), automate via cron, and avoid common pitfalls.
Why choose rsync for remote backups
Rsync is efficient because it only transfers changed blocks, not whole files, and supports many options for preservation, compression, and exclusion. For remote backups it uses SSH by default (secure) and can be scripted easily for automation.
Basic syntax:
# Basic one-off push: local -> remote
rsync -avz /path/to/source/ user@backup.example.com:/path/to/destination/
Explanation:
- -a: archive mode (recursive, preserves symlinks, permissions, timestamps, owner/group)
- -v: verbose
- -z: compress during transfer
A simple pull (remote -> local):
# Pull data from remote to local
rsync -avz user@backup.example.com:/path/to/remote/ /local/backup/
Use rsync for periodic backups, mirrored repositories, or one-off transfers. The remainder of this guide focuses on making these operations automated, reliable, and safe.
Set up SSH key-based authentication
Automation requires non-interactive login. Generate an SSH key on the machine initiating backups and install the public key on the backup server. This avoids manually entering passwords when cron runs rsync.
Generate a key pair (on source machine):
ssh-keygen -t ed25519 -C "backup@source" -f ~/.ssh/backup_rsa
# Leave passphrase empty for fully automated jobs (consider key security)
Copy the public key to the backup server:
ssh-copy-id -i ~/.ssh/backup_rsa.pub user@backup.example.com
# or manually append ~/.ssh/backup_rsa.pub contents to ~/.ssh/authorized_keys on the server
Test the key-based login:
ssh -i ~/.ssh/backup_rsa user@backup.example.com 'echo "SSH OK"'
Tip: Create a dedicated backup user on the server with restricted shell access or chroot if you want to limit what the backup key can do.
Creating and tuning your rsync command
This section brings together practical rsync examples, and a commands table that explains common options. Start with a script or single-line command, test with dry-run, then enable destructive options (like --delete) only after verifying.
Example: mirror home directory to remote, preserve permissions, compress, and delete removed files on source:
rsync -azh --delete --progress --exclude='Downloads/' \
/home/alice/ user@backup.example.com:/backups/alice/
- --delete: removes files on destination that no longer exist on source (use carefully)
- --progress: show transfer progress per file
- --exclude: skip patterns or directories
Dry-run to verify what will happen:
rsync -azh --delete --dry-run /home/alice/ user@backup.example.com:/backups/alice/
Commands table (common options)
| Option | Meaning |
|---|---|
| -a | Archive mode: recursive, preserves permissions, symlinks, times |
| -v | Verbose |
| -z | Compress file data during transfer |
| -h | Human-readable numbers |
| --delete | Delete extraneous files from destination |
| --delete-after | Delete after transfer completes |
| --exclude='PATTERN' | Exclude files matching PATTERN |
| --partial --partial-dir=.rsync-partial | Keep partially transferred files (useful for large files & resume) |
| --bwlimit=KBPS | Limit I/O bandwidth (useful during business hours) |
| --link-dest=DIR | Hard-link unchanged files to save disk when doing incremental snapshots |
Example using link-dest for snapshot-style backups (keeps disk efficient):
# Make a dated snapshot, hard-linking unchanged files to previous snapshot
rsync -a --delete --link-dest=/backups/alice/2025-10-30 \
/home/alice/ user@backup.example.com:/backups/alice/2025-11-01/
Scheduling note (included here): create a wrapper script and cron entry (see next section for details), but always start with --dry-run to validate behavior.
Automating with cron (make backups run on schedule)
Wrap the rsync command in a small script for clarity, logging, and easy testing.
Example backup script: /usr/local/bin/backup-alice.sh
#!/bin/bash
LOG="/var/log/rsync-backup-alice.log"
DATE=$(date '+%F %T')
echo "Backup started: $DATE" >> "$LOG"
/usr/bin/rsync -azh --delete --partial --bwlimit=5000 \
/home/alice/ user@backup.example.com:/backups/alice/ >> "$LOG" 2>&1
echo "Backup finished: $(date '+%F %T')" >> "$LOG"
Make it executable:
chmod +x /usr/local/bin/backup-alice.sh
Cron entry to run nightly at 02:30:
# Edit crontab with: crontab -e
30 2 * * * /usr/local/bin/backup-alice.sh
Tips:
- Use absolute paths in scripts and cron.
- Pipe stdout/stderr to a log for debugging.
- Consider rotating logs (logrotate) to avoid runaway log files.
- If you must run during business hours, use --bwlimit to avoid congesting the network.
Testing cron jobs:
# Run the script manually to confirm it works
/usr/local/bin/backup-alice.sh
# Simulate cron environment quickly
env -i HOME=$HOME SHELL=$SHELL /usr/local/bin/backup-alice.sh
Common Pitfalls
SSH key issues in cron environment:
Cron may not read your normal SSH agent or environment. Ensure the key file is accessible and specify it in your rsync command via -e "ssh -i /path/to/key".
rsync -azh -e "ssh -i /home/alice/.ssh/backup_rsa" /home/alice/ user@backup.example.com:/backups/alice/
Accidentally deleting data with --delete:
Always test with --dry-run before enabling --delete. A mistyped destination path can wipe a directory you didn't intend.
rsync -az --delete --dry-run /home/alice/ user@backup.example.com:/backups/alice/
Permissions and ownership mismatches:
rsync preserves ownership by default only if run as root (on the receiving system root privileges required to set owner). If files end up with wrong owner, run as a user that matches or use --chown.
# Example to set owner:group for transferred files
rsync -azh --chown=alice:alice /home/alice/ user@backup.example.com:/backups/alice/
Next Steps
Add monitoring and alerting: monitor cron logs and implement email or chat alerts on failures (check exit codes, or scan rsync logs for "error").
# Simple exit-code check in script
/usr/bin/rsync ... || mail -s "Backup failed" admin@example.com
Encrypt sensitive backups at rest or use encrypted volumes on the backup server:
# Example symmetric encryption of a tarball before transfer
tar -czf - /home/alice/ | gpg --symmetric --cipher-algo AES256 -o /tmp/alice.tgz.gpg
rsync -avz /tmp/alice.tgz.gpg user@backup.example.com:/backups/alice/
Verify restores regularly: do a test restore to ensure backups are usable.
# Restore a file from remote to /tmp/restore-test/
rsync -avz user@backup.example.com:/backups/alice/path/to/file /tmp/restore-test/
Automating backups with rsync is powerful and efficient when you follow best practices: use SSH keys, test with dry-runs, log results, and schedule carefully. With the examples and table above you should be able to create a reproducible, automated backup workflow that fits your needs.
👉 Explore more IT books and guides at dargslan.com.