Backup VPS su Hetzner, OVH, Contabo, Digital Ocean e Aruba: strategie avanzate per aziende

Backup VPS su Hetzner, OVH, Contabo, Digital Ocean e Aruba: strategie avanzate per aziende

A settembre 2024 un cliente veneto - PMI manifatturiera con gestionale Laravel 10 su un VPS Contabo da 8 vCPU, 30 GB di RAM e 400 GB SSD - mi ha chiamato dopo che un ransomware aveva cifrato l'intero filesystem del server. Il gestionale coordinava la produzione di tre linee di assemblaggio con circa 120 ordini giornalieri, e ogni ora di fermo costava al cliente circa 4.500 euro in ritardi sulle consegne e penali contrattuali. Il backup esistente era un mysqldump schedulato ogni notte alle 02:00, salvato in /var/backups/ - sullo stesso disco del server cifrato. Inutile. Il secondo "backup" era una copia manuale del database che il titolare faceva ogni venerdì scaricando il dump via SFTP sul suo portatile. L'ultimo scaricamento risaliva a undici giorni prima. Undici giorni di ordini, fatture, note di produzione e modifiche ai listini, persi.

Quel cliente ha dovuto ricostruire manualmente undici giorni di dati dalle email e dalle copie cartacee degli ordini. Il costo totale dell'incidente - tra downtime, lavoro manuale di ricostruzione e penali contrattuali - ha superato i 35.000 euro. Un backup offsite configurato correttamente avrebbe costato meno di 10 euro al mese. In questo articolo ti racconto la strategia di backup che ho implementato per quel cliente dopo l'incidente, e che oggi applico come standard a ogni VPS che gestisco - perché è lo stesso protocollo che avrebbe evitato quel disastro.

Stai cercando un Consulente Informatico esperto per mettere in sicurezza i backup della tua infrastruttura? Nel mio profilo professionale trovi l'esperienza concreta su Hetzner, OVH, Contabo, Digital Ocean e Aruba. Contattami per una consulenza diretta.

Perché la regola 3-2-1 non basta più e cosa significa la regola 3-2-1-1-0?

La regola 3-2-1 - tre copie dei dati, su due supporti diversi, con una copia offsite - è stata per vent'anni il riferimento per la strategia di backup. Nel 2025 non basta più, perché non tiene conto del ransomware moderno. I ransomware attuali cercano e cifrano attivamente i backup raggiungibili dal server compromesso: share di rete montati, repository remoti accessibili con le stesse credenziali, bucket S3 senza object lock. Se il ransomware può raggiungere i tuoi backup, non sono backup - sono un secondo bersaglio.

La regola aggiornata è la 3-2-1-1-0, documentata da Barracuda Networks e ormai adottata come standard di settore: tre copie, due supporti, una offsite, una immutabile (non modificabile nemmeno con credenziali di root del server di produzione), e zero errori verificati con test di ripristino regolari. L'elemento cruciale è l'immutabilità: se il server di produzione viene compromesso al 100% - root access, credenziali rubate, tutto - il backup immutabile sopravvive perché il protocollo di archiviazione impedisce fisicamente la cancellazione o la modifica dei dati esistenti.

Lo strumento: BorgBackup con repository append-only

BorgBackup è lo strumento che uso come standard per i backup VPS. Le ragioni sono tre: deduplicazione a livello di blocco (che riduce lo spazio occupato del 60-80% rispetto a backup tradizionali), encryption AES-256 lato client (i dati partono cifrati dal server e arrivano cifrati allo storage, il provider non può leggerli), e supporto nativo per la modalità append-only che è il fondamento dell'immutabilità.

L'inizializzazione di un repository BorgBackup cifrato è diretta:

# Installare BorgBackup
apt install -y borgbackup

# Inizializzare il repository con encryption
# Il passphrase viene richiesto interattivamente
borg init --encryption=repokey-blake2 ssh://backup@STORAGE_IP/./borg-repo

# CRITICO: esportare e salvare la chiave del repository
# Senza questa chiave + passphrase, i backup sono irrecuperabili
borg key export ssh://backup@STORAGE_IP/./borg-repo /root/borg-key-export.txt
# Salvare borg-key-export.txt in un luogo sicuro OFFLINE

La scelta di repokey-blake2 rispetto al vecchio repokey è intenzionale: BLAKE2 è più veloce di SHA-256 per l'hashing dei chunk e produce le stesse garanzie di integrità. Su un VPS con CPU limitata, la differenza è misurabile - circa il 15% di velocità in più durante il backup.

L'append-only mode su Hetzner Storage Box

La chiave dell'immutabilità sta nella configurazione lato server del repository. Su una Hetzner Storage Box - che uso come target di backup standard per i VPS dei clienti - la configurazione append-only si implementa nel file authorized_keys dell'utente di backup:

command="borg serve --restrict-to-path /home/backup/borg-repo --append-only",restrict ssh-ed25519 AAAAC3Nza...chiave_pubblica_del_vps...

Il flag --append-only istruisce il processo borg serve ad accettare nuovi archivi e nuovi chunk di dati, ma a rifiutare qualsiasi richiesta di cancellazione o modifica. Questo significa che anche se un attaccante ottiene root sul VPS di produzione e trova la chiave SSH del backup, non può cancellare i backup esistenti. Può solo aggiungerne di nuovi. La pulizia dei backup vecchi (pruning) viene eseguita solo dalla Storage Box stessa, con un cron locale che ha credenziali diverse e non è raggiungibile dal VPS.

Per nuovi clienti Hetzner, puoi ottenere €20.00 di credito gratuito utilizzando questo link con codice sconto - una scelta ideale per aziende europee che necessitano conformità GDPR e data center in Germania.

Lo script di backup completo che uso in produzione

Lo script che installo su ogni VPS gestito esegue quattro operazioni in sequenza: dump del database, backup del filesystem con BorgBackup, pruning della retention e verifica dell'integrità. Lo eseguo come systemd timer (non come cron) per avere logging strutturato e gestione dei fallimenti.

#!/usr/bin/env bash
set -euo pipefail

# Configurazione
BORG_REPO="ssh://backup@STORAGE_IP/./borg-repo"
export BORG_PASSPHRASE="passphrase_sicura"  # in produzione: da file con chmod 600
BACKUP_NAME="{hostname}-{now:%Y-%m-%d_%H%M}"
LOG="/var/log/borg-backup.log"

log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG"; }

# 1. Dump MySQL (consistente, senza lock sulle tabelle InnoDB)
log "START: MySQL dump"
mysqldump -u backup_user -p"${MYSQL_PASS}" \
    --single-transaction --routines --triggers \
    --all-databases | gzip > /tmp/mysql-dump.sql.gz
log "DONE: MySQL dump ($(du -sh /tmp/mysql-dump.sql.gz | cut -f1))"

# 2. Backup BorgBackup
log "START: Borg create"
borg create --compression zstd,6 --stats \
    "${BORG_REPO}::${BACKUP_NAME}" \
    /etc \
    /var/www \
    /home \
    /tmp/mysql-dump.sql.gz \
    --exclude '/var/www/*/vendor' \
    --exclude '/var/www/*/node_modules' \
    --exclude '/var/www/*/storage/logs/*.log' \
    --exclude '*.cache' \
    2>> "$LOG"
log "DONE: Borg create"

# 3. Pulizia dump temporaneo
rm -f /tmp/mysql-dump.sql.gz

# 4. Verifica integrità (settimanale, il sabato)
if [ "$(date +%u)" -eq 6 ]; then
    log "START: Borg check"
    borg check --verify-data "${BORG_REPO}" 2>> "$LOG"
    log "DONE: Borg check"
fi

# 5. Notifica (email o Telegram)
LAST_ARCHIVE=$(borg list --last 1 --format '{name} {time}' "${BORG_REPO}" 2>/dev/null)
log "Ultimo archivio: ${LAST_ARCHIVE}"

Le esclusioni sono importanti: vendor/ e node_modules/ sono rigenerabili con composer install e npm ci, quindi includerli nel backup spreca spazio e tempo. I log di Laravel in storage/logs/ sono utili per il debug ma non per il ripristino. La compressione zstd,6 offre un eccellente rapporto compressione/velocità - circa il 50% di riduzione con overhead CPU minimo.

Il --single-transaction nel mysqldump è fondamentale: garantisce che il dump sia consistente senza bloccare le tabelle InnoDB. Senza questo flag, un dump su un database attivo può produrre dati inconsistenti - una tabella ordini con righe che referenziano prodotti non ancora dumpati.

La retention policy: quanti backup tenere e per quanto tempo

La retention segue il modello GFS (Grandfather-Father-Son) che bilancia granularità di ripristino e costo dello storage:

  • 7 backup giornalieri - per recuperare da errori recenti
  • 4 backup settimanali - per recuperare da problemi scoperti in ritardo
  • 6 backup mensili - per audit, compliance e recovery da corruzione lenta

Su BorgBackup la retention si configura così:

# Pruning (eseguito SOLO dalla Storage Box, non dal VPS)
borg prune --keep-daily=7 --keep-weekly=4 --keep-monthly=6 \
    --stats "${BORG_REPO}" 2>> "$LOG"

# Compattazione dello spazio dopo il pruning
borg compact "${BORG_REPO}" 2>> "$LOG"

Il borg compact dopo il pruning è un passaggio che molti dimenticano: il pruning marca gli archivi come eliminati, ma lo spazio viene effettivamente liberato solo con il compact. Senza compact, la Storage Box continua a crescere anche dopo il pruning.

Per il cliente veneto, con un database MySQL da 8 GB e un filesystem applicativo da 12 GB, la deduplicazione di Borg riduce lo storage effettivo a circa 15 GB totali per l'intera retention (7+4+6 = 17 archivi), perché la maggior parte dei file non cambia tra un giorno e l'altro. Il costo della Hetzner Storage Box da 1 TB è 3,81 euro al mese - meno del caffè quotidiano.

Il test di ripristino automatizzato: la parte che tutti saltano

Un backup che non è mai stato testato non è un backup - è una speranza. Lo dico con cognizione di causa: in almeno tre occasioni ho visto clienti scoprire che i loro backup erano corrotti o incompleti proprio nel momento in cui ne avevano bisogno. Il motivo è quasi sempre lo stesso: nessuno aveva mai verificato che il ripristino funzionasse.

Il test di ripristino che configuro su ogni VPS estrae l'ultimo archivio Borg in una directory temporanea, verifica che i file critici esistano e abbiano dimensione non-zero, e importa il dump MySQL in un database di test per verificare l'integrità:

#!/usr/bin/env bash
set -euo pipefail

# Test di ripristino (eseguito ogni domenica notte)
TEST_DIR="/tmp/restore-test-$(date +%Y%m%d)"
mkdir -p "$TEST_DIR"

# Estrarre l'ultimo archivio
LAST=$(borg list --last 1 --format '{name}' "${BORG_REPO}")
borg extract --dry-run "${BORG_REPO}::${LAST}" 2>/tmp/borg-restore-test.log

# Verificare che il dry-run non abbia errori
if [ $? -eq 0 ]; then
    echo "RESTORE TEST OK: ${LAST}" | mail -s "Backup OK" [email protected]
else
    echo "RESTORE TEST FAILED: ${LAST}" | mail -s "BACKUP ALERT" [email protected]
fi

rm -rf "$TEST_DIR"

Il --dry-run di borg extract verifica l'integrità dell'archivio senza estrarre effettivamente i file, il che lo rende veloce e privo di impatto sullo spazio disco. Una volta al mese eseguo un test completo con estrazione reale e import del dump MySQL in un database temporaneo, ma il test settimanale con dry-run è sufficiente per catturare la maggior parte dei problemi di corruzione.

Il backup del database: mysqldump non è l'unica opzione

Per database MySQL o MariaDB sotto i 10 GB, mysqldump con --single-transaction resta lo strumento più pratico: produce un file SQL leggibile, portabile e verificabile manualmente. Ma per database più grandi - sopra i 20-30 GB - il tempo di dump diventa un problema. Un mysqldump di un database da 40 GB può richiedere 45-60 minuti, durante i quali le transazioni lunghe tengono una vista consistente del database che può generare problemi di performance.

Per questi casi uso Percona XtraBackup, che esegue backup fisici hot senza bloccare le scritture. XtraBackup copia i file InnoDB a livello di pagina mentre il database continua a operare, e applica i redo log al termine per garantire la consistenza. Il ripristino è più veloce di un import SQL perché non deve ricostruire gli indici - si copiano i file e si avvia MySQL. Lo svantaggio è che il backup non è portabile tra versioni diverse di MySQL, ma per il disaster recovery sullo stesso stack è la soluzione più efficiente.

Un errore che vedo spesso: il mysqldump viene schedulato ma nessuno controlla mai se è andato a buon fine. Lo script che ho mostrato sopra logga ogni operazione, ma il passo in più che implemento sempre è un check sulla dimensione del dump - se il file è significativamente più piccolo del solito (più del 20% di variazione), qualcosa è andato storto e il backup va segnalato come sospetto.

Cosa cambia per i diversi provider

Ogni provider ha le sue specificità per quanto riguarda lo storage di backup:

Hetzner offre le Storage Box (da 1 TB a 20 TB, da 3,81€/mese) con supporto SSH/SFTP nativo - ideali per BorgBackup via SSH. Supportano anche snapshot automatici per i Cloud VPS (a pagamento, 20% del costo del VPS) ma li considero un complemento, non un sostituto del backup offsite.

OVH offre backup automatico dello snapshot per i VPS (incluso in alcuni piani), ma la granularità è limitata e il ripristino è del tipo tutto-o-niente. Per backup granulari serve uno storage esterno - il loro Object Storage con compatibilità S3 è un'opzione, ma il pricing è meno competitivo di Hetzner.

Contabo non offre soluzioni di backup integrate di qualità paragonabile. Il mio approccio standard è usare una Hetzner Storage Box come target di backup anche per VPS Contabo - la latenza tra data center europei è trascurabile per backup notturni.

Digital Ocean offre Spaces (object storage compatibile S3) a 5$/mese per 250 GB, utilizzabile con rclone per sincronizzare i backup Borg. Offre anche backup automatici dei Droplet a un costo del 20% aggiuntivo.

In tutti i casi, il principio è lo stesso: il backup deve essere su un'infrastruttura separata dal server di produzione, con credenziali diverse e modalità append-only. Se il backup e il server sono nello stesso account, un singolo compromise li distrugge entrambi. Ho documentato un caso specifico di intrusione su VPS con eradicazione e ripristino in cui la disponibilità di backup offsite ha fatto la differenza tra quattro ore di downtime e quattro settimane.

Ho descritto il framework completo di disaster recovery - di cui il backup è il primo pilastro - nell'articolo sul piano di disaster recovery per applicazioni PHP. E se il tuo caso specifico riguarda un backup Laravel che fallisce silenziosamente, ho documentato la diagnosi e la soluzione nell'articolo sulla strategia urgente per backup falliti su VPS Laravel.

Il backup non è un task tecnico da delegare e dimenticare - è un'assicurazione sulla sopravvivenza del tuo business digitale. Ogni giorno senza un backup offsite, immutabile e testato è un giorno in cui stai scommettendo che non succederà nulla di grave. Il cliente veneto ha perso quella scommessa, e il conto è stato di 35.000 euro. Una Hetzner Storage Box con BorgBackup costa meno di 50 euro l'anno. Se vuoi implementare una strategia di backup seria sulla tua infrastruttura, o se vuoi verificare che quella attuale funzioni davvero, contattami.

Ultima modifica: