Recipes

One job per section: what it is for, the command, and what to watch out for. Every one of these assumes you have read the trailing-slash rule — it is the difference between a backup and a mess.

Back up a home folder to an external disk

The most common reason to install rsync. --delete makes the disk a true mirror, so files you removed do not accumulate on it forever.

bash
# preview first — see quick start, step 2
rsync -av --delete --dry-run ~/ /media/backup/laptop/

# then for real
rsync -av --delete ~/ /media/backup/laptop/

You almost certainly do not want caches and build directories in a backup. Keep the patterns in a file so the command stays readable:

bash
rsync -av --delete --exclude-from=$HOME/.backup-excludes ~/ /media/backup/laptop/
~/.backup-excludes
.cache/
.local/share/Trash/
node_modules/
*.tmp

Keep dated snapshots without paying for them twice

A single mirror has one weakness: if you delete a file and do not notice for a week, the mirror has faithfully deleted it too. Dated snapshots fix that, and --link-dest makes them nearly free — files that have not changed since the previous snapshot become hard links to it rather than second copies.

bash
TODAY=$(date +%F)
cd /media/backup
rsync -av --delete --link-dest=/media/backup/latest ~/ "/media/backup/$TODAY/"
ln -snf "/media/backup/$TODAY" /media/backup/latest

Each dated directory looks like a complete backup and can be browsed and restored from with ordinary tools, but only the changes take up new space:

bash
du -sh /media/backup/*
 41G	/media/backup/2026-08-10
112M	/media/backup/2026-08-11
 98M	/media/backup/2026-08-12

This replaces the rotating-backup script on the original examples page, which emptied and reused a directory per weekday. That approach still works, but it gives you seven snapshots at most and needs a script; --link-dest gives you as many as your disk will hold, in four lines. One deliberate change: the original script authenticates with RSYNC_PASSWORD set in the environment, and these recipes use SSH keys instead, so no password is ever written into a file or exported into a shell.

Deploy a built site to a web server

Upload only what changed, and remove files that no longer exist in the build — no stale pages left behind from three deploys ago. -z compresses in transit, which is worth it for text.

bash
rsync -avz --delete ./dist/ you@server.example.com:/var/www/example.com/

Careful with -a when the destination is a web server. -a preserves your local ownership and permissions, which is rarely what a web root wants. Setting the modes explicitly is usually safer:

bash
rsync -rvz --delete --chmod=D755,F644 ./dist/ you@server.example.com:/var/www/example.com/

Pull files down from a server

Same command, arguments the other way round. Logs are the usual case:

bash
rsync -avz you@server.example.com:/var/log/nginx/ ./logs/nginx/

Move a directory tree to another machine intact

When you are migrating a server rather than backing it up, you want everything preserved: hard links, ACLs and extended attributes as well as the ordinary metadata. --numeric-ids keeps numeric owners rather than remapping them through the names on the receiving machine.

bash
sudo rsync -aHAXv --numeric-ids /srv/data/ you@newserver:/srv/data/

Run it twice — once while the service is still up, then again after stopping it. The second run only has to carry what changed in between, which is what keeps the downtime short.

Mirror a public archive

Public rsync servers expose modules you can copy from directly with an rsync:// URL. The rsync project publishes its own release archive this way, and rsync-ssl wraps the connection in TLS:

bash
# the rsync project's own archive, over SSL
rsync-ssl -av rsync://download.samba.org/rsyncftp/ ./rsync-archive/

Get a big transfer over an unreliable link

-P keeps partial files so an interrupted run picks up where it stopped instead of starting the file again, and --timeout makes rsync give up on a stalled connection rather than hanging until you notice.

bash
rsync -avzP --timeout=120 bigfiles/ you@server.example.com:/srv/bigfiles/

If transfers keep dying anyway, that has its own page: the transfer stops partway through.


These cover the common jobs; the reference has every option, and the project's own examples page keeps the contributed scripts these were rewritten from.