Why I keep a weekly backup copy of my home directory on an external SSD using rsync
I’m not a “data‑hoarder” in the sense of storing every file I own. I keep a single, up‑to‑date snapshot of my ~/ on a 2 TB SSD that I plug into my workstation once a week. The copy is made with rsync, stored on a separate partition, and I run a quick restore test every month. The routine feels like a small ritual that gives me confidence without eating bandwidth or storage.
Below is the exact workflow I use, why I chose each piece, and the trade‑offs I’ve seen in practice.
Why a weekly backup?
- Recovery point objective (RPO) – I rarely delete or modify large files. A weekly snapshot guarantees that I can recover any accidental deletion or corruption that happened within the last seven days.
- Minimal overhead – The external SSD is offline most of the time, so the backup never competes with my daily workload.
- Simplicity – A single, deterministic
rsyncrun is easier to audit and maintain than a complex incremental system that relies on external services.
The alternative would be a full‑system backup or a cloud sync. Both have drawbacks: full‑system backups are slow, cloud syncs can be expensive and expose personal data, and incremental tools (e.g., timeshift, btrfs send/receive) require a dedicated filesystem that I don’t use for my home directory.
Choosing the right storage
I use a 2 TB Samsung 870 QVO SSD in a USB‑3.1 enclosure. The SSD is formatted with ext4 and has a dedicated partition (/mnt/backup) that is mounted only when the backup script runs. The enclosure’s firmware supports power‑on/off detection, so the SSD stays powered only during the backup window.
Why ext4?
- Mature, well‑tested on kernel 6.x.
- Good support for large files and journaling.
- No need for snapshots;
rsynchandles incremental changes.
Why USB‑3.1?
- Fast enough for a 2 TB transfer (~200 MiB/s).
- Cheap and widely supported on both my workstation and the spare laptop I use for restore tests.
Rsync setup
I keep the backup script in ~/scripts/backup_home.sh. The script is intentionally short and idempotent.
#!/usr/bin/env bash
set -euo pipefail
SRC="$HOME/"
DEST="/mnt/backup/home-backup"
LOG="/var/log/backup_home.log"
# Mount the SSD if not already mounted
if ! mountpoint -q "$DEST"; then
sudo mount /dev/sdb1 "$DEST"
fi
# Rsync options:
# -a: archive mode (preserves perms, timestamps, symlinks)
# -v: verbose
# -h: human‑readable output
# --delete: remove files in DEST that no longer exist in SRC
# --progress: show transfer progress
# --stats: summary after completion
rsync -avh --delete --progress --stats "$SRC" "$DEST" >>"$LOG" 2>&1
# Unmount after completion
sudo umount "$DEST"
Key points
| Option | Why it matters |
|---|---|
-a |
Keeps ownership and permissions intact. |
--delete |
Prevents the backup from growing indefinitely. |
--stats |
Gives a quick health check (bytes transferred, errors). |
--progress |
Useful when running manually; omitted in automated runs. |
The script is run via a systemd timer (see next section) and logs to /var/log/backup_home.log. I review the log weekly to catch any rsync errors.
Automation with systemd timers
Systemd timers are a lightweight alternative to cron, and they integrate cleanly with the rest of the system. I create two unit files:
/etc/systemd/system/backup-home.service
[Unit]
Description=Backup home directory to external SSD
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup_home.sh
/etc/systemd/system/backup-home.timer
[Unit]
Description=Run backup-home.service every Sunday at 02:00
[Timer]
OnCalendar=Sun *-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Enable the timer:
sudo systemctl enable --now backup-home.timer
The timer fires every Sunday at 02:00 local time. I chose a low‑traffic hour to avoid competing with other users on the machine. The Persistent=true flag guarantees that if the system is down at the scheduled time, the job runs immediately after boot.
Testing the restore
A backup is only useful if I can actually restore from it. I reserve a spare laptop (a 2015 Dell Latitude) as a “restore target.” The laptop has a clean install of Ubuntu 24.04 and a fresh ext4 partition that I mount as /mnt/restore.
Step 1 – Mount the backup SSD
sudo mount /dev/sdb1 /mnt/backup
Step 2 – Verify the snapshot
rsync -avh --dry-run --delete "$HOME/" /mnt/restore/
The --dry-run flag shows what
See also
- Why ssh keeps spawning new processes on every connect and how ControlPersist solves it
- Repairing a broken initramfs that locked my Raspberry Pi in emergency mode after a kernel update
- How I added ionice ‑c3 to my nightly rsync backup and finally stopped my laptop from overheating
- Running a nightly backup script after logout with systemd user units – no nohup needed
- I lost SSH access to my home server after accidentally setting /home/user to 777 – how I restored it with a live USB