Snapshot backups with rsync give each backup run its own dated directory while unchanged files share the same inode through hard links. An operator can browse or restore from any snapshot like a full copy, but the backup volume stores another copy only for files that changed.
The --link-dest option compares the new destination with a previous snapshot and links matching files into the new tree. A relative link target is resolved from the destination directory, so --link-dest=../2026-06-06 points from /backup/rsync/2026-06-07/ back to the prior dated snapshot.
Create every snapshot in an empty directory and let source writes settle before the run. Rsync normally selects changed files by size and modification time, hard-linked snapshots are not application-aware database backups, and --inplace does not belong in this workflow because it can rewrite an older snapshot through a shared inode.
Steps to create snapshot backups with rsync:
- Record the source directory, snapshot root, and dated destination names before running rsync.
Source: /srv/data/ Snapshot root: /backup/rsync/ First snapshot: /backup/rsync/2026-06-06/ Next snapshot: /backup/rsync/2026-06-07/
- Create the first dated snapshot directory.
$ mkdir -p /backup/rsync/2026-06-06
- Copy the source tree into the first snapshot.
$ rsync -ai --delete /srv/data/ /backup/rsync/2026-06-06/ >f+++++++++ index.html cd+++++++++ releases/ >f+++++++++ releases/v1.txt
The trailing slash on /srv/data/ copies the contents of the source directory into the snapshot directory.
Use a new dated destination for each snapshot. Reusing an older snapshot path lets --delete remove files from that snapshot.
- Create an empty directory for the next snapshot after the source changes.
$ mkdir -p /backup/rsync/2026-06-07
- Run the next snapshot with the previous snapshot as the hard-link source.
$ rsync -ai --delete --link-dest=../2026-06-06 /srv/data/ /backup/rsync/2026-06-07/ >f.s....... index.html >f+++++++++ releases/v2.txt
The relative --link-dest value is evaluated from /backup/rsync/2026-06-07/, so ../2026-06-06 points to the prior snapshot in the same root. Unchanged files that were linked from the prior snapshot do not appear in the itemized output.
- Compare one unchanged file across both snapshots to confirm hard-link reuse.
$ ls -li /backup/rsync/2026-06-06/releases/v1.txt /backup/rsync/2026-06-07/releases/v1.txt 2627130 -rw-r--r-- 2 root root 10 Jun 6 03:41 /backup/rsync/2026-06-06/releases/v1.txt 2627130 -rw-r--r-- 2 root root 10 Jun 6 03:41 /backup/rsync/2026-06-07/releases/v1.txt
The same inode number and link count of 2 show that both snapshot paths refer to one unchanged file on disk.
- Create a temporary restore directory for a smoke test.
$ mkdir -p /tmp/restore-test
- Restore the new snapshot into the temporary directory.
$ rsync -ai /backup/rsync/2026-06-07/ /tmp/restore-test/ >f+++++++++ index.html cd+++++++++ releases/ >f+++++++++ releases/v1.txt >f+++++++++ releases/v2.txt
A restore test proves the snapshot tree can be copied back out, not only that the backup command exited.
- Read a restored file that came from the hard-linked snapshot content.
$ cat /tmp/restore-test/releases/v1.txt release 1
- Remove the temporary restore directory after the smoke test.
$ rm -rf /tmp/restore-test
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.