What Does the Rsync Remote Backup Script Look Like?
A local-only backup dies with the machine. Whether it's disk failure, ransomware, or an accidental rm -rf, data stored only on one host has a single point of failure. This script pushes an incremental mirror to a remote server over SSH — transferring only the bytes that changed since the last run.
How it works, line by line
SOURCE_DIR="/home/user/projects/"— Trailing slash means "contents of this directory," not the directory itself. Without it, rsync creates aprojects/subdirectory at the destination.-a(archive) — Preserves permissions, ownership, timestamps, symlinks, and directory structure. Equivalent to-rlptgoD.-v(verbose) — Prints each file as it transfers. Remove for cron runs where you only care about errors.-z(compress) — Compresses data in transit. Saves 60-80% bandwidth on text files. Skip for already-compressed data (images, video, archives).--delete— Removes destination files that no longer exist on the source. Keeps the remote an exact mirror.--partial— Keeps partially transferred files instead of deleting them. Next run resumes from where it left off.-e "ssh -i $SSH_KEY"— Specifies the SSH key for authentication. Always use key-based auth for automated backups.--exclude-from— Reads exclusion patterns from a file:node_modules,.git,*.log, etc.--bwlimit— Caps bandwidth in KB/s. Set to avoid saturating a shared connection during business hours.
How Do I Set Up and Run the Rsync Backup Script?
Step 1: Verify SSH key access
Before rsync can work, you need passwordless SSH access to the remote server:
If this fails, set up SSH keys first with the SSH key setup script.
Step 2: Create the exclude file
Add patterns for directories you never want to back up:
Step 3: Run a dry-run first
Never run a destructive operation (--delete) without previewing what it will do:
The --dry-run flag shows exactly what would be transferred and deleted — without touching any files.
Step 4: Execute the real backup
First run transfers everything. Subsequent runs only send changed blocks — a 10 GB source with 50 MB of daily changes completes in seconds.
What Are Common Variations of This Script?
Variation 1: Backup with versioned snapshots (hardlinks)
Creates daily snapshots that look like full copies but share unchanged files via hardlinks — using minimal extra disk space:
Variation 2: Bandwidth-limited daytime backup
For shared office connections where a full-speed rsync would saturate upstream:
--bwlimit=5000 caps transfer at 5 MB/s — enough for a background backup without making video calls stutter.
Variation 3: Backup multiple directories to one destination
How Do I Automate This with Cron?
Open your crontab:
Add a nightly backup at 2 AM when traffic is lowest:
Cron environment has no SSH agent
Cron runs without your interactive shell environment. The script must reference the SSH key path directly (-e "ssh -i /path/to/key"), or the connection will fail with Permission denied. Never rely on ssh-agent for cron-scheduled backups.
rsync your backups to a DigitalOcean droplet or Spaces — offsite in one command.
Get $200 free credit — DigitalOcean
Get $200 Free →Affiliate link · we earn a commission
Related Scripts
- Automated File Backup — Local cp-based backups with date-stamped directories
- MySQL Database Backup — Dump and compress databases before rsync ships them offsite
- SSH Key Setup Script — Generate and deploy the SSH key rsync needs for passwordless access
FAQ
What do the rsync flags -avz actually do?
The -a flag (archive) preserves permissions, ownership, timestamps, symlinks, and directory structure — equivalent to -rlptgoD. The -v flag (verbose) prints each file as it transfers so you can watch progress. The -z flag (compress) compresses data during transfer, reducing bandwidth by 60-80% for text-heavy directories. Together they form the standard rsync invocation for backups.
Does --delete remove files from my source?
No. --delete only affects the destination. It removes files on the remote that no longer exist on the source, keeping the destination as an exact mirror. Without --delete, renamed or removed source files accumulate as orphans on the destination, wasting space indefinitely. Always run --dry-run first to preview what would be deleted.
How do I resume an interrupted rsync transfer?
Add the --partial flag. Without it, rsync deletes partially transferred files on interruption and restarts them from zero on the next run. With --partial, incomplete files are kept and resumed from where they left off. For large files over unreliable connections, also add --partial-dir=.rsync-tmp to store partials in a hidden directory.
How do I exclude directories from an rsync backup?
Use --exclude for each pattern: --exclude='node_modules' --exclude='.git' --exclude='*.tmp'. For many exclusions, create a file listing one pattern per line and pass --exclude-from='/path/to/excludes.txt'. Patterns are matched against the relative path from the source directory.
Is rsync secure over the internet?
Yes, when using -e ssh (the default on modern systems). All data travels through an encrypted SSH tunnel. The remote server never sees unencrypted traffic. For additional security, restrict the SSH key used for backups to rsync-only commands using command= in authorized_keys on the destination.