Skip to main content

rsync: Server Synchronization and Backups

Migration · 01.02.2025 · 4 min read
Illustration for “rsync: Server Synchronization and Backups”

What rsync is

rsync is a utility for efficiently syncing files between servers. It transfers only the parts of files that changed, which makes it ideal for incremental backups and for moving site files between hosting providers without wasting bandwidth.

💡 rsync transfers only the delta (changes) between files, not the whole file — this saves up to 90% of traffic when backing up large sites.

An order for transferring site files with no downtime

  1. Run a first full sync of files to the new server while the old site keeps running.
  2. Repeat the sync right before the switch — it copies only the files that changed since the first pass.
  3. Check the new server through the hosts file, without touching the domain's DNS.
  4. Switch the domain and immediately run a final rsync with the --delete flag, to remove files deleted on the old server during the move.
  5. Keep the old server reachable for a few more days in case a rollback is needed.

The real downtime with this order is only for switching DNS or the web server, usually one to five minutes, not the hours a full file copy takes.

Key rsync flags

FlagDescription
-aArchive mode (recursion + permissions + metadata)
-vVerbose output
-zCompression during transfer
--deleteDelete files on the destination that no longer exist on the source
--excludeExclude files/folders
--dry-runA test run with no real changes
--link-destHard links for incremental backups

Basic sync between servers

# Sync a folder to a remote server
rsync -avz --delete   /var/www/mysite/   user@backup-server:/backups/mysite/

# With exclusions
rsync -avz --delete   --exclude='wp-content/cache/'   --exclude='*.log'   /var/www/mysite/   user@backup-server:/backups/mysite/

Checking the result without a real transfer

Before the first run on real data, always run the command with the --dry-run flag — rsync shows the list of files it would copy or delete without touching anything on disk:

rsync -avz --delete --dry-run   /var/www/mysite/   user@backup-server:/backups/mysite/
#!/bin/bash
DATE=$(date +%Y-%m-%d_%H%M)
DEST=/backups/mysite
LATEST=$DEST/latest

rsync -avz --delete   --link-dest=$LATEST   /var/www/mysite/   $DEST/$DATE/

# Update the pointer to the latest backup
rm -f $LATEST
ln -s $DEST/$DATE $LATEST

--link-dest creates hard links to unchanged files instead of copying them — each snapshot looks like a full copy but only actually uses disk space for files that changed.

Comparing file transfer scenarios with rsync

ScenarioCommandTrait
One-off transfer of all filesrsync -avz source destinationno deletion on the destination
Mirroring (exact match)rsync -avz --delete source destinationremoves extra files on the destination
Daily backup with historyrsync -avz --link-dest=previoussaves disk space

Common errors

MessageCause and fix
rsync: connection unexpectedly closedThe SSH connection dropped, or the remote server ran out of memory — retry with the --partial flag to resume
Permission denied (publickey)The SSH key is not added on the remote server — copy it with ssh-copy-id
rsync error: some files/attrs were not transferredNot enough rights to change file ownership — run with sudo on both sides, or drop -o -g from archive mode

Rollback in case of problems

  1. Do not delete files on the old server until you confirm the new one works normally for at least a full day.
  2. If files turn out to be missing after the switch, run a reverse sync from the old server to the new one, without --delete.
  3. Find the cause of the mismatch (usually an --exclude pattern that caught files it should not have) and repeat the transfer.

When rsync does not fit

--delete removes files on the destination without warning. Always use --dry-run the first time. For databases, rsync copies the DBMS file "as is" and can transfer it in an inconsistent state if the database server is running during the copy — databases need mysqldump or pg_dump, not an rsync of the data files.

Automating with cron

# Daily backup at 3 AM
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Checking the result

  • Compare file counts: find /var/www/mysite | wc -l should match on the source and destination.
  • Check the checksum of a few key files: md5sum on both sides.
  • Open the site through the hosts override and confirm all static files load without a 404.

Migrating a database that needs to stay in sync with the files is covered in migrating a MySQL database, and a general post-move site check is in post-migration check.

Was this article helpful?
← Back to Knowledge Base Ask Support