rsync over SSH: backup incrementali a costo zero

Published on 03/05/2026 Linux

rsync è uno strumento Unix vecchio ma indistruttibile. Trasferisce solo i delta tra origine e destinazione, supporta SSH come trasporto, e con l'opzione --link-dest permette snapshot incrementali stile Time Machine senza duplicare i file invariati.

1. Backup base verso un NAS

rsync -avzP /home/marco/ marco@nas.local:/volume1/backups/marco/

Flag spiegati:

  • -a archive: preserva permessi, timestamp, symlink, ecc.
  • -v verbose: mostra cosa fa.
  • -z comprime durante il transfer (utile su Wi-Fi/WAN).
  • -P progresso + resume parziali.

2. Esclusioni

Non vuoi backuppare cache, build, node_modules:

rsync -avz \
  --exclude '.cache/' \
  --exclude 'node_modules/' \
  --exclude '*.tmp' \
  /home/marco/ marco@nas.local:/volume1/backups/marco/

Per esclusioni lunghe, mettile in un file:

# ~/backup-excludes.txt
.cache/
node_modules/
.git/objects/pack/
*.iso
*.tmp

# Uso:
rsync -avz --exclude-from=~/backup-excludes.txt \
  /home/marco/ marco@nas.local:/volume1/backups/marco/

3. Snapshot incrementali con --link-dest

L'idea: ogni notte crei una nuova cartella per la data corrente, ma i file invariati sono hard-link alla notte precedente. Costo spazio: solo i file modificati.

#!/bin/bash
DEST=marco@nas.local:/volume1/backups/marco
TODAY=$(date +%Y-%m-%d)
LATEST=$(ssh marco@nas.local "readlink /volume1/backups/marco/latest" 2>/dev/null || echo "")

rsync -avz --delete \
  --link-dest=../$LATEST \
  --exclude-from=~/backup-excludes.txt \
  /home/marco/ \
  $DEST/$TODAY/

# Aggiorna il symlink "latest"
ssh marco@nas.local "cd /volume1/backups/marco && rm -f latest && ln -s $TODAY latest"

Risultato dopo 30 giorni: 30 cartelle datate, ognuna sembra un backup completo, ma in totale occupano poco più della singola "ultima copia" + il delta cumulato.

4. Verifica

Per controllare che gli hard-link funzionino:

ssh marco@nas.local "du -sh /volume1/backups/marco/2026-05-08"
ssh marco@nas.local "du -shc /volume1/backups/marco/*"

La somma del secondo comando NON sarà uguale alla somma delle singole — l'overlap è condiviso.

5. Restore

Per ripristinare il backup di una data specifica:

rsync -avz marco@nas.local:/volume1/backups/marco/2026-05-08/ ~/restore-2026-05-08/

6. Schedulazione

Aggiungi a systemd timer (o cron):

# /etc/systemd/system/backup-home.service
[Unit]
Description=Backup giornaliero della home
[Service]
Type=oneshot
User=marco
ExecStart=/home/marco/scripts/backup.sh

# /etc/systemd/system/backup-home.timer
[Unit]
Description=Backup giornaliero
[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true
[Install]
WantedBy=timers.target

7. Pulizia degli snapshot vecchi

Dopo qualche mese servirà rimuovere snapshot oltre i 90 giorni. Aggiungi in fondo allo script:

ssh marco@nas.local "cd /volume1/backups/marco && find . -maxdepth 1 -type d -mtime +90 -name '20*' -exec rm -rf {} +"
Attento al --delete: rimuove dal backup i file rimossi dall'origine. È quello che vuoi per "specchio aggiornato", non per "voglio recuperare un file cancellato 2 mesi fa". Per quello servono gli snapshot.