What rsync actually does
You run `rsync -a` for the first time and it copies everything. You run it again an hour later and it copies almost nothing, yet the destination is identical. That gap — between what you asked for and what actually moved — is the whole reason rsync survived three decades of backup tools that came and went.
This is not a tutorial. It is a piece about choosing. rsync is one option among several, and the choice depends on things you know about your own setup and I do not. What follows is what each option costs you.
What rsync actually does
rsync copies files. That is the boring description. The interesting part is how it decides what not to copy.When you point rsync at a source and a destination, it does not compare whole files. It splits the destination file into blocks, hashes them, sends those hashes to the source, and the source replies with only the blocks that differ. This is the delta encoding the man page mentions in passing. The practical effect: a 40 GB database dump with a few changed rows moves a few megabytes over the wire, not forty gigabytes.
That single property is why rsync became the default answer for backups on Unix-like systems. It is also why it is a poor fit for some jobs, which we will get to.
The first decision: what are you protecting against
Before you pick a flag, pick a failure mode. rsync solves one specific problem very well: keeping a second copy of a filesystem in sync with the first. It solves that problem for local disks, for remote servers over SSH, and for rsync daemons listening on port 873.It does not solve ransomware. If something encrypts your source files and you run rsync on schedule, your destination gets encrypted too. `--delete` makes this worse, not better. A mirrored backup is not a backup against deletion; it is a copy that follows you off the cliff.
It does not solve accidental deletion either, unless you configure it to. Which brings us to the flag that ruins more data than any other.
`--delete` and what it costs
By default rsync adds and updates. It never removes. Your destination accumulates files that no longer exist on the source, which is either a feature or a slow-motion disk-filling problem depending on how long you let it run.`--delete` fixes that by making the destination an exact mirror. Files removed from the source are removed from the destination. This is what you want for a true mirror. It is also what turns a mistyped path into a very bad afternoon.
If you want deletion to propagate but you want a way back, `--backup --backup-dir=/path/to/archive` moves the deleted and overwritten files into a dated directory instead of destroying them. You get version history without a version control system. The cost is disk space and the discipline to prune that archive before it fills the volume.
The Arch Wiki is blunt about this and worth reading before you enable `--delete` on anything you care about.
`-a` is not one flag
`-a` expands to `-rlptgoD`. Recursive, preserve symlinks, permissions, timestamps, group, owner, devices. It is the flag people type without thinking, and it is usually right for backups.It is wrong when the destination filesystem does not support what it preserves. Copying from ext4 to a FAT32 USB stick with `-a` will throw errors on ownership and permissions. Use `-rlt` instead and accept that the stick does not care who owned the file.
It is also wrong when you are copying to a system where the numeric UIDs mean something different. Preserving ownership across two machines with different user databases produces files owned by nobody. `--no-owner --no-group` fixes it. You lose the metadata; you keep the files.
`-z` and when it hurts
Compression during transfer sounds free. It is not. On a fast local network, `-z` spends CPU to save bandwidth you were not using, and the transfer gets slower. On a slow link, it pays for itself immediately.The rule of thumb: use `-z` over WAN, skip it on LAN. Modern SSH already compresses if you ask it to, and double compression is just wasted cycles. Pick one layer and let the other alone.
SSH versus daemon mode
`rsync -e ssh user@host:/src /dst` is the default for a reason. You get authentication, encryption, and access control from a tool you already run. Nothing new to expose. Nothing new to patch.Daemon mode is different. You run `rsync --daemon`, it reads `/etc/rsyncd.conf`, and it listens on port 873. Clients connect without SSH. This is faster — no encryption overhead, no SSH handshake per connection — and it scales to many clients hitting one server.
It is also unauthenticated by default. Modules can be world-readable if you are careless with the config. The rsync protocol has no transport encryption. You are one firewall misconfiguration away from serving your backups to anyone who runs `rsync rsync://yourhost/`.
There is `rsync-ssl` for wrapping the daemon in TLS, but at that point you have reinvented SSH with extra steps and a certificate to renew.
If you need daemon mode for scale, put it behind a firewall, restrict by IP, and treat the module list as a security boundary. If you do not need it, do not run it.
The other flags worth knowing
`-u` (update) skips files that are newer on the destination. Useful when two systems push to the same target and you do not want the older copy to win. Dangerous when you actually wanted the older copy to win and forgot you set it.`-n` (dry run) with `-v` shows you exactly what would happen without doing it. Run this before every `--delete` operation for the first month. Then keep running it, because the one time you skip it is the time it matters.
`--partial` keeps partially transferred files so a dropped connection does not restart from zero. `--partial-dir` puts them somewhere specific. On flaky links this is the difference between a backup that finishes and one that never does.
`--exclude-from=file` reads patterns from a file. For anything beyond a handful of exclusions, use this instead of stacking `--exclude` flags on the command line. The command stays readable and the patterns stay in version control.
Where rsync stops being the right answer
rsync is a synchronizer. It is not a backup system with retention, not a snapshot mechanism, and not a deduplicating archive.If you need point-in-time recovery to last Tuesday, rsync alone will not give it to you. You can fake it with `--backup-dir` and dated directories, but you are now writing your own retention policy and your own pruning script. At some point you are maintaining a worse version of `borgbackup` or `restic`.
Those tools do content-defined chunking, deduplication across snapshots, and encryption at rest. They cost you a repository format you cannot browse with `ls`. rsync's destination is just files. That is its greatest strength and its ceiling.
For a single server backing up to a NAS, rsync plus a cron job plus `--backup-dir` is fine. For a fleet of machines with compliance requirements, it is not.
For the closed alternatives — Veeam, Acronis, the commercial agents — they handle scheduling, retention, reporting, and a support contract. They cost money and they will not run on a shell account. They are also genuinely good at what they do, and pretending otherwise helps nobody.
What it comes down to
rsync rewards understanding. Every flag has a cost, and the defaults are conservative for a reason. The tool will not stop you from deleting your destination, overwriting a newer file, or compressing a transfer that did not need it.The choice is not rsync versus something else. It is whether you want to know exactly what your backup does, or whether you want to pay someone to know it for you. Both are legitimate. Only one of them means you are the one reading the man page at eleven at night when the cron job fails.