TL;DR:
-
Back up to dated snapshots using
--link-dest
so each day looks full but uses hard links. -
Keep an exclude file, don’t recurse into
/proc
,/sys
, etc., and avoid infinite loops by excluding the backup path itself. -
After every run, prove you can restore one file and one directory.
-
Rotate snapshots (e.g., keep 30 dailies, 12 monthlies). Log everything.
1) Scope and baseline
This guide covers Linux server backups with rsync (local or over SSH). Two common patterns:
-
Data-only (recommended for most):
/etc
,/home
, app data (e.g.,/var/www
,/srv/*
). -
Whole-system: root filesystem without pseudo-filesystems and caches.
Either way, snapshots are dated directories plus a latest
symlink:
2) Exclude file (save as /etc/rsync/excludes.txt
)
For whole-system style. Trim if you’re doing data-only.
Uncomment paths you actually have. If you do data-only, you don’t need most of this—just back up the selected trees.
3) First full snapshot (local disk)
Choose a destination (example): /mnt/backup/$(hostname -s)
.
Flags explained (brief):
-
-aHAXx
→ archive, hardlinks, ACLs, xattrs, stay on this filesystem. -
--numeric-ids
→ preserve uids/gids numerically (safer across hosts). -
--info=stats2,progress2
→ usable logging without chatty noise.
Data-only variant (back up only key trees):
4) Daily snapshots with --link-dest
(incrementals that look full)
Create /usr/local/sbin/rsync-snapshot.sh
:
Schedule (choose one):
-
cron:
sudo crontab -e
-
systemd timer (more reliable):
-
/etc/systemd/system/rsync-snapshot.service
-
/etc/systemd/system/rsync-snapshot.timer
-
Activate:
-
--delete
removes files deleted at source in the current snapshot; prior snapshots retain them thanks to hard links. Review your comfort level before enabling.
5) Offsite (over SSH)
Back up to a remote host backup@backupbox
into /srv/backup/$(hostname -s)/$DATE/
:
Hardening tip: create a backup
user on the remote box with limited permissions and an SSH forced-command if you want to restrict what rsync can do.
6) Verify restores (every run, not once a year)
Single file
Directory
Whole snapshot dry-run (sanity check)
On SELinux systems, follow restores with
restorecon -R /path
as required.
7) Logging and rotation
Add --log-file=/var/log/rsync-backup.log
to your rsync command(s) if you want full logs, then set logrotate
:
/etc/logrotate.d/rsync-backup
:
8) Common pitfalls (avoid these)
-
Trailing slash semantics:
rsync SRC/ DEST/
copies contents of SRC;rsync SRC DEST/
creates a subdirDEST/SRC
. Be explicit. -
Recursion into backups: always exclude the backup path (or keep destination on a different filesystem/mount).
-
Permissions not preserved: use
-a
, and include-A -X -H
where you care about ACLs, xattrs, hard links. -
UID/GID mismatch: add
--numeric-ids
. -
No restore proof: schedule a monthly restore test to a temporary path and document the steps.
9) Minimal checklist
-
Exclude file in place and correct for your system.
-
First snapshot completes;
latest
symlink points to it. -
Daily job scheduled (cron or systemd timer).
-
One file restored and verified.
-
One directory restored and verified.
-
Retention removes old snapshots (confirm).
-
Offsite copy (SSH) working, or at-rest encryption on the backup disk (e.g., LUKS).
Security gaps in Linux and cloud systems risk downtime, data compromise, lost business — and compliance failures.
With 20+ years’ experience and active UK Security Check (SC) clearance, I harden Linux and cloud platforms for government, corporate, and academic sectors — ensuring secure, compliant, and resilient infrastructure.