CASE STUDY • HOMELAB • PROXMOX & ZFS

Storage ZFS su Proxmox:
Pool Multipli, PBS su NAS e Nextcloud via NFS

Un homelab che cresce diventa rapidamente un problema di storage. Non nel senso che manca lo spazio — nel senso che ogni servizio ha esigenze diverse, e trattare tutti i dati allo stesso modo è la strada più veloce verso performance scadenti, backup inaffidabili o, nel peggiore dei casi, perdita di dati.

In questo articolo racconto come ho strutturato lo storage sul nodo principale del mio cluster Proxmox: pool ZFS diversi per carichi diversi, un NAS esterno come datastore per Proxmox Backup Server via NFS, Nextcloud con architettura ibrida, e un incident reale con un pool DEGRADED dopo un reboot — con la diagnosi e la soluzione.

1. La Logica dei Pool ZFS Multipli

ZFS non è solo un filesystem — è un gestore di storage completo che gestisce RAID, compressione, deduplicazione, snapshot e checksum di integrità. Ma la sua flessibilità richiede anche decisioni consapevoli: non tutti i tipi di storage si comportano allo stesso modo sotto diversi carichi.

Nel mio setup il nodo principale ha quattro pool con caratteristiche e ruoli distinti:

La regola pratica che seguo: un database non va mai su HDD, indipendentemente dalla ridondanza. La latenza di un HDD in random read/write è incompatibile con MariaDB o PostgreSQL sotto carico. E un container generico non ha bisogno del pool NVMe più veloce — sprecare NVMe su un container che fa poco è come usare un SSD da 10.000 IOPS per archivio PDF.

2. NAS Esterno come Datastore PBS via NFS

Proxmox Backup Server è il componente che gestisce i backup incrementali di VM e container nel cluster. La domanda è: dove mettere i dati di backup? Metterli sullo stesso nodo che si sta backuppando è una pessima idea — se il nodo muore, perdi sia i dati che il backup.

La soluzione è un NAS esterno che espone una share NFS, montata nel container PBS. Il flusso è:

  1. Il NAS espone la share via NFS (es. /srv/proxmox-backup)
  2. Il container PBS monta la share in /mnt/nas-backup via fstab con opzione _netdev
  3. PBS usa /mnt/nas-backup/pbs-lz come datastore
  4. Tutti i nodi del cluster puntano a questo PBS come storage di backup

Il mount in fstab con _netdev è fondamentale: dice al sistema di montare questa share solo dopo che la rete è attiva. Senza questa opzione, un reboot causa mount fallito e PBS non si avvia correttamente.

# /etc/fstab nel container PBS
nas-ip:/srv/proxmox-backup  /mnt/nas-backup  nfs  defaults,_netdev,soft,timeo=30  0  0

Il Problema di root_squash

Quasi tutti i server NFS hanno root_squash attivo per default — e giustamente, perché è una misura di sicurezza. Il problema è che root_squash significa che qualsiasi operazione NFS eseguita come root viene rimappata a un utente anonimo (tipicamente nobody con UID 65534).

Questo crea un problema specifico con i container LXC in Proxmox, dove i processi girano con UID remappati. Nel caso di Nextcloud, il web server Apache/PHP gira come www-data. Se la data directory di Nextcloud è su NFS, tutte le operazioni sui file devono essere eseguite con l'UID corretto — e quell'UID deve avere i permessi giusti sul NAS.

La diagnosi: se Nextcloud dà errori di scrittura sulla data directory e i log mostrano permission denied, prima di cercare altrove verifica che l'UID del processo corrisponda al proprietario della directory sul NAS:

# Nel container, verifica l'UID effettivo di www-data
id www-data

# Sul NAS, verifica il proprietario della directory
ls -lan /srv/nextcloud-data/

# Se non corrispondono, correggi
chown -R UID:GID /srv/nextcloud-data/

3. Nextcloud con Architettura Ibrida

Nextcloud ha due componenti con esigenze molto diverse: il codice applicativo + database (che richiedono velocità) e la data directory dove vivono i file degli utenti (che richiede capacità).

Mescolarli sullo stesso storage è un compromesso che penalizza entrambi. La soluzione è l'architettura ibrida:

Il vantaggio di questa architettura è che puoi scalare i due storage indipendentemente: aggiungi HDD al pool bulk quando finisci lo spazio per i file, senza toccare gli NVMe dove gira il codice.

Una considerazione importante: Nextcloud fa molta I/O sul database anche per operazioni apparentemente semplici (navigazione della UI, sync client). Il database su NVMe è quindi quasi sempre la scelta giusta, anche se i file degli utenti stanno su HDD.

💡 Vuoi costruire un'infrastruttura simile per la tua azienda? Scopri i nostri servizi di infrastruttura oppure richiedi una consulenza.

4. Incident Reale: Pool ZFS DEGRADED dopo Reboot

Questo è il tipo di problema che non trovi nei tutorial ma che prima o poi colpisce chiunque usi ZFS con NVMe su Linux.

Il sintomo: dopo un reboot del nodo, uno dei pool NVMe risulta in stato DEGRADED. Il comando zpool status mostra uno o più device come UNAVAIL con un path che non esiste più.

La causa: Linux assegna i nomi ai device NVMe (nvme0n1, nvme1n1, ecc.) in base all'ordine di enumerazione del bus PCIe al boot. Questo ordine non è deterministico — può cambiare tra un reboot e l'altro, specialmente se cambi hardware, aggiorni il kernel, o il BIOS enumera i dispositivi in ordine diverso. ZFS crea il pool con quei nomi, e al reboot successivo lo stesso disco fisico potrebbe chiamarsi nvme3n1 invece di nvme0n1.

La diagnosi:

# Verifica lo stato del pool
zpool status nome-pool

# Trova il GUID del device mancante nell'output di zpool status
# Poi cerca il device fisico per GUID
zdb -l /dev/nvme0n1 | grep -i guid
zdb -l /dev/nvme1n1 | grep -i guid
# ... ripeti per tutti i device NVMe presenti

La soluzione rapida quando il pool è DEGRADED per device rename è un export + import forzato:

zpool export nome-pool
zpool import nome-pool

ZFS durante l'import scansiona i device disponibili cercando quelli con il GUID corrispondente al pool — indipendentemente dal nome kernel attuale. Se i dischi fisici sono presenti, li trova e ricostruisce la mappatura.

La soluzione definitiva — quella che previene il problema invece di correggerlo — è usare sempre i nomi persistenti per i device ZFS. Linux espone i device con identificatori stabili in /dev/disk/by-id/:

# Trova i nomi persistenti dei tuoi NVMe
ls -la /dev/disk/by-id/ | grep nvme

# Crea o ricrea il pool con nome persistente
zpool create nome-pool /dev/disk/by-id/nvme-Samsung_SSD_xxxxx-part1

# Per un pool esistente, sostituisci il device con il nome persistente
zpool replace nome-pool nvme0n1 /dev/disk/by-id/nvme-Samsung_SSD_xxxxx

Dopo questa operazione, ZFS memorizza il path by-id invece del nome kernel. Al prossimo reboot, il pool si importa correttamente indipendentemente dall'ordine di enumerazione.


Le Lezioni Apprese

Tre principi che si sono consolidati lavorando su questo setup:

Vuoi un'infrastruttura server affidabile per la tua azienda?

Progettiamo e gestiamo infrastrutture server, backup e storage per PMI e professionisti a Firenze e nel Chianti.

Richiedi una consulenza