Vai al contenuto

Deployment di un Hypervisor Proxmox VE NIS2 Compliant su OVH

Meta

  • Autore: 4Sparks SRL
  • Audience: Tecnici IT / Sysadmin
  • Uso: Referenza interna 4Sparks + deliverable commerciale clienti
  • Scenario: Nodo singolo Proxmox VE 9.x su server dedicato OVH
  • Lingua: Italiano (terminologia tecnica in inglese dove standard)

Indice e Appunti per Sezione

1. Introduzione

1.1 Scopo del Documento

Questo manuale descrive la procedura completa per il deployment e l'hardening di un hypervisor Proxmox VE 8.x su server dedicato OVH, con l'obiettivo di soddisfare i requisiti tecnici previsti dalla Direttiva NIS2 (EU 2022/2555) e dal suo recepimento italiano (D.Lgs. 138/2024).

Il documento è destinato a tecnici IT e system administrator incaricati della messa in opera e gestione di infrastrutture virtualizzate in contesti soggetti a NIS2 o che adottano volontariamente standard di sicurezza equivalenti.

1.2 Ambito

Il manuale copre il deployment di un singolo nodo Proxmox VE su server bare metal OVH, con il seguente stack tecnologico:

Componente Tecnologia
Hypervisor Proxmox VE 9.x (Debian 13 Trixie based)
Firewall / Gateway pfSense CE (VM) + Proxmox Firewall integrato
Storage ZFS con crittografia nativa + LUKS
SIEM / Monitoring Wazuh
Backup Proxmox Backup Server (locale + remoto)
Provider hosting OVH Bare Metal (linea Advance / Scale)

L'evoluzione a cluster multi-nodo è trattata nell'Appendice A.

1.3 Riferimenti Normativi

  • Direttiva (UE) 2022/2555 (NIS2) — Capo IV, Art. 21 (Misure di gestione del rischio di cybersicurezza) e Art. 23 (Obblighi di segnalazione)
  • D.Lgs. 4 settembre 2024, n. 138 — Recepimento italiano della Direttiva NIS2
  • CIS Benchmark Debian Linux 13 (o 12 se non ancora disponibile per Trixie) — Riferimento per l'hardening del sistema operativo
  • CIS Benchmark Proxmox VE (se disponibile) — Riferimento complementare
  • ISO/IEC 27001:2022 — Annex A, utilizzato come framework di controllo integrativo

1.4 Limiti e Disclaimer

Questo manuale copre esclusivamente i controlli tecnici implementabili a livello infrastrutturale. La compliance NIS2 richiede anche misure organizzative che esulano dall'ambito di questo documento, tra cui:

  • Governance e policy di sicurezza a livello aziendale
  • Formazione e sensibilizzazione del personale (Art. 21(2)(g))
  • Gestione della sicurezza della supply chain oltre il fornitore di hosting
  • Valutazione e trattamento formale dei rischi (risk assessment documentato)
  • Nomina del responsabile della sicurezza e struttura organizzativa

L'implementazione di questo manuale non garantisce di per sé la compliance NIS2, ma costituisce la componente tecnica fondamentale di un programma di conformità più ampio.

1.5 Convenzioni

In tutto il documento:

  • I comandi da eseguire come root sono preceduti da #, quelli come utente non privilegiato da $
  • I placeholder sono indicati tra parentesi angolate: <VALORE_DA_SOSTITUIRE>
  • I blocchi di configurazione riportano il percorso del file come commento nella prima riga
  • Le note di sicurezza critiche sono evidenziate con ⚠ ATTENZIONE
  • I riferimenti NIS2 sono indicati in calce a ogni sezione nel formato: Rif. NIS2: Art. 21(2)(x)

2. Requisiti e Scelta del Server OVH

  • Linee prodotto consigliate: Advance-2 / Scale (ECC RAM, IPMI/KVM)
  • Requisiti minimi consigliati: 64GB+ RAM ECC, 2x SSD NVMe (mirror ZFS), 1Gbps+ uplink
  • Opzioni OVH da configurare in fase d'ordine:
    • Sistema operativo: installazione custom via KVM/IPMI (no template OVH)
    • vRack: attivare se si prevede segmentazione L2 o multi-server futuro
    • IP aggiuntivi / IP failover: per pfSense WAN
    • Backup storage OVH (opzionale, complementare a PBS)
  • Note: evitare RAID hardware OVH se si usa ZFS (conflitto controller)
  • Dati da annotare prima dell'installazione:
    • Da General Information (pannello OVH Manager → Bare Metal Cloud → Server):
      • IP principale del server
      • Gateway
      • Netmask (tipicamente /24)
      • DNS OVH (213.186.33.99) o DNS preferiti
    • Da Network Interfaces (stessa sezione):
      • MAC address dell'interfaccia pubblica — serve per la configurazione dei bridge Proxmox e per l'assegnazione dell'IP failover alla VM pfSense
    • Questi dati servono durante l'installer Debian per la configurazione di rete e non sono facilmente recuperabili a installazione in corso.
  • ⚠ ATTENZIONE — Monitoring OVH: prima di avviare qualsiasi operazione di installazione, disattivare il monitoring OVH dal pannello Manager (Bare Metal Cloud → Server → Monitoring → Disattiva). Se lasciato attivo, OVH rileva il server come irraggiungibile durante l'installazione e può riavviarlo automaticamente in modalità rescue, interrompendo il processo. Riattivare il monitoring solo a installazione e configurazione di base completate (vedi §3 post-install).

3. Installazione Base (Debian 13 Trixie + Proxmox VE 9.x)

L'installazione parte da Debian 13 (Trixie) minimal anziché dall'ISO Proxmox. Motivazione: l'installer Proxmox non consente il controllo granulare sul partitioning necessario per la conformità CIS Benchmark (partizioni separate per /tmp, /var, /var/log, /var/log/audit, ecc.) né la configurazione di LUKS a livello di block device durante l'installazione.

Fase 1 — Installazione Debian 13 Minimal

  • ISO: scaricare la ISO netinst di Debian 13 (Trixie) da https://www.debian.org/distrib/netinst, verificare checksum SHA256

  • Montaggio ISO via KVM OVH:

    1. Accedere al pannello OVH Manager → IPMI/KVM
    2. Aprire la console KVM (Web o Java)
    3. Montare la ISO netinst (pulsante in alto a destra, "Virtual Media" o equivalente)
    4. Inviare Ctrl+Alt+Del al server (Send Ctrl+Alt+Del)
    5. Durante il POST, premere F11 per il boot menu
    6. Selezionare AMI Virtual CDROM come dispositivo di boot
    7. Avviare l'installazione Debian (consigliata modalità testuale, più leggera via KVM remoto)
    8. ⚠ CDROM virtuale: la console KVM web di OVH smonta il virtual CDROM quando perde il focus (cambio tab, cambio finestra, ALT+TAB). Potrebbe anche smontarsi dopo un periodo di inattività (nessuna lettura dal media per un certo tempo). Evitare di spostare il focus dalla finestra della console durante l'installazione. Quando l'installer mostra l'errore "media not found" o simile, riaprire il menu Virtual Media e rimontare la ISO, poi selezionare "Retry" nell'installer. Se l'installer schianta e non si riesce a fare Retry, aprire una shell con Alt+F2 ed eseguire:
    Text Only
    umount /cdrom
    mount /dev/sr0 /cdrom
    

    Poi tornare all'installer con Alt+F1 e riprovare. Consiglio pratico: usare un secondo dispositivo (telefono, tablet, altro PC) per consultare il pannello OVH o la documentazione durante l'installazione.

  • Metodo alternativo — kexec da rescue mode (se il montaggio ISO via KVM non funziona):
    Se il virtual CDROM dà troppi problemi o non è disponibile, è possibile avviare l'installer Debian direttamente dal rescue mode OVH tramite kexec:

    1. Avviare il server in rescue mode dal pannello OVH (Netboot → Rescue)
    2. Accedere via SSH al rescue mode
    3. Aprire la console IPMI KVM prima di procedere — dopo il kexec la sessione SSH muore
    4. Eseguire:
    Text Only
    # apt update && apt install -y kexec-tools
    # cd /tmp
    # wget http://ftp.debian.org/debian/dists/trixie/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux
    # wget http://ftp.debian.org/debian/dists/trixie/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz
    # kexec -l /tmp/linux --initrd=/tmp/initrd.gz --append="console=tty0"
    # kexec -e
    

    Il server riavvia direttamente nell'installer Debian via rete (netboot), senza bisogno di ISO. L'installazione prosegue normalmente dalla console IPMI KVM. Al termine, reimpostare il netboot su disco locale dal pannello OVH prima di riavviare.

  • Lingua e locales:

    • Lingua installer: English
    • Country: selezionare Italy (per timezone e mirror corretti)
    • Locales: en_US.UTF-8 — questa è la scelta corretta per un server. I log e gli errori in inglese sono più facili da cercare, parsare e correlare. I tool di sicurezza (Wazuh, auditd, CIS benchmark) si aspettano output in inglese. La selezione "Italy" come country garantisce comunque timezone, keyboard layout e mirror corretti.
    • Tastiera: layout appropriato (es. Italian)
  • Rete: configurazione statica con IP/gateway/DNS annotati nella §2

  • Hostname: FQDN (es. node01.dominio.it)

  • Utenti:

    • root: impostare password robusta
    • Utente normale: l'installer Debian richiede la creazione di un utente non privilegiato. Usare un nome operativo senza suffisso "admin" (es. davide, operatore). L'account amministrativo dedicato verrà creato successivamente nella fase di hardening (§4) con permessi e audit trail appropriati.
    • Partitioning scheme conforme CIS Benchmark (Debian 13):

    • Selezionare il partizionamento manuale nell'installer (NON "Guided partitioning")

    • ⚠ Nota Trixie: Debian 13 configura /tmp come tmpfs di default (fino al 50% RAM) con pulizia automatica dei file. Poiché creiamo una partizione /tmp dedicata, questa impostazione viene sovrascritta dal nostro fstab. Verificare post-install che /tmp sia effettivamente la partizione dedicata e non il tmpfs di default.

    L'architettura storage è: RAID1 (mdadm) per l'OS + ZFS mirror per lo storage VM. Se un NVMe muore, il server continua a funzionare sia per l'OS che per le VM. Su un nodo singolo senza cluster, perdere il disco OS significa downtime totale.

    Step 1 — Inizializzare entrambi i dischi

    Selezionare ciascun disco (/dev/nvme0n1, poi /dev/nvme1n1) e confermare "Yes" per creare una nuova tabella partizioni GPT. Entrambi i dischi mostreranno "FREE SPACE".

    Step 2 — Creare le partizioni su nvme0n1

    Selezionare il FREE SPACE sotto /dev/nvme0n1 e creare le partizioni seguenti, una alla volta:

    # Dimensione Use as Note
    1 512 MB EFI System Partition Partizione UEFI, non cifrata
    2 2 GB physical volume for RAID Per RAID1 /boot — impostare Bootable flag: on
    3 150 GB physical volume for RAID Per RAID1 → LUKS → LVM (OS)
    4 resto (~400 GB) do not use Riservato per ZFS mirror (configurato post-install da CLI)

    Per ogni partizione: selezionare FREE SPACE → "Create a new partition" → dimensione → "Beginning" → configurare "Use as" → Done.

    L'opzione "Partition name" è solo un'etichetta GPT descrittiva (non il mount point). Suggerimenti: EFI, boot, os-raid, zfs-data.

    Step 3 — Replicare le stesse partizioni su nvme1n1

    Creare le stesse identiche partizioni su /dev/nvme1n1:

    # Dimensione Use as
    1 512 MB EFI System Partition
    2 2 GB physical volume for RAID
    3 150 GB physical volume for RAID
    4 resto (~400 GB) do not use

    Risultato atteso (verificare prima di procedere):

    Text Only
    /dev/nvme0n1:  #1 ~510MB ESP | #2 2.0GB raid | #3 150.0GB raid | #4 ~808GB
    /dev/nvme1n1:  #1 ~510MB ESP | #2 2.0GB raid | #3 150.0GB raid | #4 ~808GB
    

    Step 4 — Configurare Software RAID (mdadm)

    Dalla schermata principale, selezionare "Configure software RAID" → "Yes" per scrivere le modifiche.

    Creare MD0 (mirror per /boot):

    • "Create MD device" → RAID1 → 2 active devices, 0 spare
    • Selezionare: /dev/nvme0n1p2 e /dev/nvme1n1p2

    Creare MD1 (mirror per OS):

    • "Create MD device" → RAID1 → 2 active devices, 0 spare
    • Selezionare: /dev/nvme0n1p3 e /dev/nvme1n1p3

    → "Finish"

    Step 5 — Configurare volumi crittografati (LUKS)

    Dalla schermata principale, selezionare "Configure encrypted volumes" → "Yes" per scrivere.

    • "Create encrypted volumes"
    • Selezionare solo /dev/md1 (il RAID1 da 150GB per l'OS)
    • ⚠ NON selezionare md0 — /boot deve restare non crittografato, altrimenti GRUB non può avviare il sistema
    • Encryption method: dm-crypt (LUKS)
    • Inserire la passphrase (robusta, annotarla immediatamente)
    • "Finish"

    ⚠ IMPORTANTE: annotare la passphrase LUKS e custodirla in modo sicuro (password manager, busta sigillata off-site). Senza questa passphrase il server non può avviarsi.

    Step 6 — Configurare LVM

    Dalla schermata principale, selezionare "Configure the Logical Volume Manager" → "Yes" per scrivere.

    Creare il Volume Group:

    • "Create volume group" → nome: vg0
    • Selezionare il device crittografato (sarà qualcosa tipo /dev/mapper/md1_crypt)

    Creare i Logical Volume (uno alla volta: "Create logical volume" → selezionare vg0 → nome → dimensione):

    Nome LV Dimensione
    lv_root 40 GB
    lv_tmp 8 GB
    lv_var 25 GB
    lv_var_tmp 5 GB
    lv_var_log 15 GB
    lv_var_log_audit 8 GB
    lv_home 5 GB
    lv_swap 16 GB
    Totale ~122 GB (headroom ~28GB su 150GB)

    → "Finish"

    Step 7 — Assegnare mount point e filesystem

    Nella schermata principale, selezionare ciascun Logical Volume e configurare:

    LV Use as Mount point Mount options
    lv_root ext4 / defaults
    lv_tmp ext4 /tmp noexec, nosuid, nodev
    lv_var ext4 /var defaults
    lv_var_tmp ext4 /var/tmp noexec, nosuid, nodev
    lv_var_log ext4 /var/log defaults
    lv_var_log_audit ext4 /var/log/audit defaults
    lv_home ext4 /home nodev, nosuid
    lv_swap swap area

    Configurare anche il RAID non crittografato:

    Device Use as Mount point
    md0 ext4 /boot

    Step 8 — Finalizzare

    Selezionare "Finish partitioning and write changes to disk" → confermare.

    /dev/shm — aggiungere in /etc/fstab post-install: tmpfs /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0

  • ⚠ Backup LUKS header subito dopo l'installazione: # cryptsetup luksHeaderBackup /dev/md1 --header-backup-file /root/luks-header.bak — copiare off-site immediatamente

  • Kernel: l'installer chiede quale kernel installare. Selezionare linux-image-amd64 (meta-pacchetto che punta all'ultimo kernel stabile). Viene rimosso successivamente quando si installa il kernel Proxmox.

  • Initrd drivers: selezionare "generic: include all available drivers". Con lo stack mdadm + LUKS + LVM è necessario che l'initrd contenga tutti i moduli per sbloccare la catena di boot (RAID → decrypt → LVM → mount). Con "targeted" si rischia che manchi qualcosa. Il kernel verrà comunque sostituito con quello Proxmox.

  • Software selection: quando l'installer chiede quali pacchetti installare, selezionare solo "SSH server" e "standard system utilities" — niente GUI, niente ambiente desktop. Proxmox installa i propri pacchetti per QEMU e LXC.

    • Se si seleziona accidentalmente un ambiente desktop, rimuoverlo al primo boot:

      Text Only
      # tasksel --list-tasks
      # apt purge task-desktop task-gnome-desktop gnome* xorg* --autoremove -y
      
  • Primo boot e verifica rete: una volta completata l'installazione e riavviato il server, verificare la connettività di rete:

    Text Only
    # ping -c 3 8.8.8.8
    # ping -c 3 google.com
    

    Se non naviga, verificare che l'IP sia assegnato all'interfaccia con il MAC address corretto (quello annotato nella §2 da "Network Interfaces" su OVH):

    Text Only
    # ip a
    # ip link show
    

    Confrontare il MAC visibile con quello annotato. Se l'IP è assegnato all'interfaccia sbagliata, correggere in /etc/network/interfaces specificando l'interfaccia corretta.

Fase 2 — Preparazione Sistema per Proxmox

  • Migrazione da NetworkManager a ifupdown (requisito Proxmox):
    Debian 13 con ambiente desktop installa NetworkManager, ma Proxmox richiede ifupdown/ifupdown2 per la gestione dei bridge e delle VLAN. ⚠ Eseguire questi step con la console KVM aperta — se si sbaglia la configurazione di rete, SSH diventa irraggiungibile.

    Identificare l'interfaccia di rete:

    Text Only
    # nmcli connection show
    

    Annotare il nome dell'interfaccia (colonna DEVICE, es. enx12af6a9a0bcb o eno1, enp1s0). Il nome può essere basato sul MAC address (formato enx<MAC>).

    Installare ifupdown2 prima di toccare NetworkManager (serve la rete attiva):

    Text Only
    # apt install ifupdown2 -y
    

    Configurare /etc/network/interfaces:

    Text Only
    cat > /etc/network/interfaces << 'EOF'
    auto lo
    iface lo inet loopback
    
    auto <INTERFACCIA>
    iface <INTERFACCIA> inet static
        address <IP_PUBBLICO>/24
        gateway <GATEWAY>
        dns-nameservers 213.186.33.99
    EOF
    

    Solo ora disabilitare NetworkManager e attivare ifupdown:

    Text Only
    # systemctl stop NetworkManager
    # systemctl disable NetworkManager
    # ifup <INTERFACCIA>
    # ping -c 3 8.8.8.8
    

    Se il ping funziona, la rete è configurata correttamente. Se non si è installato un ambiente desktop durante l'installer, NetworkManager potrebbe non essere presente e la rete sarà già gestita da ifupdown — verificare con nmcli device status (se il comando non esiste, ifupdown è già attivo).

  • Configurare hostname e /etc/hosts correttamente (requisito Proxmox):

    Text Only
    # /etc/hosts
    <IP_PUBBLICO>    node01.dominio.it node01
    127.0.0.1        localhost
    
    • ⚠ ATTENZIONE: hostname --ip-address deve restituire l'IP pubblico, NON 127.0.0.1. Proxmox non funziona correttamente se il nome host risolve a localhost.
    • Verificare: # hostname --ip-address → deve restituire l'IP pubblico

Fase 3 — Installazione Proxmox VE 9.x

  • Aggiungere la chiave GPG Proxmox (posizione aggiornata per Trixie):

    Text Only
    # wget https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg -O /usr/share/keyrings/proxmox-archive-keyring.gpg
    
    • Verificare checksum:
    Text Only
    # sha256sum /usr/share/keyrings/proxmox-archive-keyring.gpg
    136673be77aba35dcce385b28737689ad64fd785a797e57897589aed08db6e45
    
  • Aggiungere il repository Proxmox (formato deb822, nuovo standard Trixie):

    Text Only
    # cat > /etc/apt/sources.list.d/pve-install-repo.sources << EOL
    Types: deb
    URIs: http://download.proxmox.com/debian/pve
    Suites: trixie
    Components: pve-no-subscription
    Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
    EOL
    
  • Aggiornare e installare il kernel Proxmox (primo step, richiede reboot):

    Text Only
    # apt update && apt full-upgrade
    # apt install proxmox-default-kernel
    # reboot
    
  • Dopo il reboot con kernel PVE, installare il resto:

    Text Only
    # apt install proxmox-ve postfix open-iscsi chrony
    
    • Postfix: scegliere "Local only" — non serve come relay. Per le notifiche email (backup job, alert), Proxmox 9.x ha un sistema di notifiche integrato configurabile da Datacenter → Notifications → Add → SMTP, che punta direttamente a un relay SMTP esterno (mail server aziendale, Brevo, ecc.) con autenticazione. Più affidabile e sicuro che inviare email direttamente da un IP OVH senza PTR/DKIM.
    • chrony: per NTP (requisito NIS2 per correlazione temporale dei log). Proxmox raccomanda chrony e sconsiglia systemd-timesyncd su server.
    • Rimuovere kernel Debian stock:
    Text Only
    # apt remove linux-image-amd64 'linux-image-6.12*'
    # update-grub
    
  • Rimuovere os-prober (non necessario, evita warning):

    Text Only
    # apt remove os-prober
    
  • Creazione bridge vmbr0 (requisito Proxmox):

    Proxmox richiede un bridge di rete (vmbr0) per funzionare. Installando Proxmox su Debian, il bridge non viene creato automaticamente. Bisogna spostare l'IP dalla NIC fisica a vmbr0 e agganciare la NIC come bridge port. ⚠ Operazione critica: se la configurazione è errata si perde l'accesso di rete. Avere la console KVM/IPMI aperta prima di procedere.

    Identificare il nome dell'interfaccia fisica attuale:

    Text Only
    # ip -br a
    

    Annotare il nome (es. enx12af6a9a0bcb, eno1, enp1s0) e l'IP/gateway attuali.

    Riscrivere /etc/network/interfaces con bridge in un'unica operazione:

    Text Only
    cat > /etc/network/interfaces << 'EOF'
    auto lo
    iface lo inet loopback
    
    # NIC fisica — nessun IP, solo bridge port
    auto <INTERFACCIA>
    iface <INTERFACCIA> inet manual
    
    # Bridge Proxmox — prende l'IP che era sulla NIC
    auto vmbr0
    iface vmbr0 inet static
        address <IP_PUBBLICO>/24
        gateway <GATEWAY>
        bridge-ports <INTERFACCIA>
        bridge-stp off
        bridge-fd 0
        dns-nameservers 213.186.33.99
    EOF
    

    Applicare la configurazione:

    Text Only
    # ifreload -a
    

    Se si usa ifupdown classico (non ifupdown2):

    Text Only
    # systemctl restart networking
    

    Verificare immediatamente:

    Text Only
    # ip a show vmbr0
    # ping -c 3 8.8.8.8
    

    Se la connessione è persa, dalla console KVM/IPMI correggere /etc/network/interfaces e riprovare.

    Dopo questa configurazione, vmbr0 è il bridge management di Proxmox e la web UI sarà raggiungibile su https://<IP>:8006.

Fase 4 — Configurazione Storage ZFS

  • Verificare prima i nomi delle partizioni riservate per ZFS:

    Text Only
    # lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
    

    Identificare le partizioni più grandi (~808GB) su entrambi i dischi che non hanno mount point — sono quelle riservate per ZFS. Nell'esempio di questo manuale corrispondono a /dev/nvme0n1p4 e /dev/nvme1n1p4, ma il nome potrebbe variare in base all'hardware.

  • Creare il pool ZFS mirror sulle partizioni riservate:

    Text Only
    # zpool create -o ashift=12 rpool mirror /dev/nvme0n1p4 /dev/nvme1n1p4
    

    ⚠ ATTENZIONE: usare le partizioni identificate con lsblk, NON i dischi interi — altrimenti si sovrascrivono le partizioni OS/boot/EFI.

  • Abilitare ZFS native encryption sul dataset VM/CT:

    Text Only
    # zfs create -o encryption=aes-256-gcm -o keyformat=passphrase rpool/data
    

    Non è necessario un dataset separato per i backup locali: Proxmox Backup Server cifra già lato client (AES-256-GCM) e i backup devono risiedere su un PBS remoto, non sullo stesso nodo (single point of failure).

  • Aggiungere lo storage in Proxmox:

    • Datacenter → Storage → Add → ZFS
    • ID: Data
    • ZFS Pool: rpool/data
    • Content: Disk image, Container
    • Thin provision: ✓ (attivare — ZFS gestisce nativamente lo spazio, senza thin Proxmox pre-alloca l'intero disco VM sprecando spazio)
    • Block Size: 16k
    • → Add
    • Configurare scrub periodico:
    Text Only
    # systemctl enable zfs-scrub-weekly@rpool.timer
    

Fase 5 — Post-Install

  • Rimuovere repo enterprise (se no subscription):

    Text Only
    # rm /etc/apt/sources.list.d/pve-enterprise.list 2>/dev/null
    # rm /etc/apt/sources.list.d/pve-enterprise.sources 2>/dev/null
    
  • Verificare accesso web UI: https://<IP>:8006

  • Configurare NTP e verificare sincronizzazione: # chronyc tracking

  • ⚠ Riattivare il monitoring OVH dal pannello Manager una volta che il nodo è raggiungibile e stabile

  • Snapshot/backup di questa configurazione base prima di procedere con l'hardening

  • Procedura di unlock al boot (da eseguire ad ogni riavvio):

    Il sistema richiede due unlock manuali distinti ad ogni reboot:

    1. Unlock LUKS (OS) — richiesto automaticamente al boot, solo via console KVM/IPMI:

    • Il sistema si ferma chiedendo la passphrase LUKS prima di montare il filesystem root
    • Inserire la passphrase → il sistema prosegue il boot

    2. Unlock ZFS (storage VM/CT) — da eseguire dopo il login, via SSH o console:

    Text Only
    # zfs load-key rpool/data
    

    Inserire la passphrase ZFS, poi:

    Text Only
    # zfs mount -a
    

    Solo dopo l'unlock ZFS le VM e i container possono avviarsi. Se le VM sono configurate con auto-start, partiranno automaticamente dopo il mount.

    ⚠ ATTENZIONE: se il server si riavvia autonomamente (crash, kernel panic, manutenzione OVH), è necessario intervenire manualmente per entrambi gli unlock. Senza intervento, l'OS non parte (LUKS) e le VM non si avviano (ZFS). Valutare un sistema di alerting sul reboot (es. Wazuh, UptimeRobot, o monitoring OVH stesso).

4. Hardening del Nodo (CIS Benchmark Debian 13 — via ovh/debian-cis)

Per l'hardening del nodo si utilizza il tool ovh/debian-cis (https://github.com/ovh/debian-cis), lo stesso set di script modulari che OVHcloud utilizza in produzione per la propria infrastruttura PCI-DSS. Supporta Debian 11/12/13. Il tool opera in due modalità: --audit (sola verifica, nessuna modifica) e --apply (applica automaticamente le remediation).

4.1 Installazione del tool

Text Only
# apt install git -y
# git clone https://github.com/ovh/debian-cis.git /opt/cis-hardening
# cp /opt/cis-hardening/debian/default /etc/default/cis-hardening
# sed -i "s#CIS_ROOT_DIR=.*#CIS_ROOT_DIR='/opt/cis-hardening'#" /etc/default/cis-hardening

4.2 Primo audit (sola lettura)

Eseguire un audit completo prima di qualsiasi modifica per avere una baseline:

Text Only
# cd /opt/cis-hardening
# bin/hardening.sh --audit-all

Il report finale mostra il numero di check passed/failed e la percentuale di conformità. Salvare l'output come baseline:

Text Only
# bin/hardening.sh --audit-all 2>&1 | tee /root/cis-audit-baseline-$(date +%Y%m%d).log

4.3 Configurare il livello di hardening

I check sono organizzati in 5 livelli di severità crescente. Per un server NIS2-compliant, impostare almeno il livello 3 (consigliato livello 4-5 per ambienti ad alta sicurezza):

Text Only
# bin/hardening.sh --set-hardening-level 5

Questo abilita/disabilita i singoli script in etc/conf.d/. È possibile personalizzare individualmente ogni check editando il relativo file .cfg:

Text Only
# ls etc/conf.d/
# nano etc/conf.d/<nome_check>.cfg

Ogni file ha status=disabled|audit|enabled.

4.4 Eccezioni e personalizzazioni per Proxmox

Alcuni check CIS vanno adattati perché Proxmox ha requisiti specifici:

  • net.ipv4.ip_forward=1: il CIS benchmark lo vuole disabilitato, ma è necessario per il funzionamento dei bridge e della VM pfSense. Escludere o adattare il check relativo.
  • Servizi Proxmox: pveproxy, pvedaemon, pvestatd, pve-cluster, corosync ecc. non vanno disabilitati. Verificare che il check sui servizi abbia le eccezioni corrette.
  • Porte aperte: la porta 8006 (web UI Proxmox) e 3128 (spiceproxy) sono legittime.

Documentare ogni eccezione e la relativa motivazione in un file dedicato:

Text Only
# nano /opt/cis-hardening/exceptions-proxmox.md

4.5 Applicare l'hardening

⚠ ATTENZIONE: assicurarsi di avere la console KVM/IPMI aperta prima di applicare — in caso di problemi con SSH o rete, è l'unico modo per accedere al server.

Text Only
# bin/hardening.sh --apply

Il tool crea backup automatici dei file modificati nella directory configurata in etc/hardening.cfg.

4.6 Audit post-hardening

Rieseguire l'audit per verificare il risultato:

Text Only
# bin/hardening.sh --audit-all 2>&1 | tee /root/cis-audit-post-hardening-$(date +%Y%m%d).log

Confrontare con la baseline. L'obiettivo è raggiungere una conformità ≥ 90%. I check residui in stato FAIL vanno documentati con motivazione (eccezione Proxmox, non applicabile, ecc.).

4.7 Hardening manuale complementare

Alcuni aspetti non sono coperti dal tool e vanno configurati manualmente:

  • Accesso IPMI/KVM OVH:

    • Cambiare password IPMI default OVH dal pannello Manager
    • Limitare accesso IPMI a IP specifici (pannello OVH → IPMI → IP restrictions)
    • Banner legale SSH (/etc/issue.net):
    Text Only
    ******************************************************************
    ATTENZIONE: Accesso riservato. Ogni attività è monitorata e
    registrata. L'accesso non autorizzato è perseguibile a norma di
    legge (Art. 615-ter c.p.).
    ******************************************************************
    

    In /etc/ssh/sshd_config: Banner /etc/issue.net

  • Audit periodico: schedulare l'audit CIS con cron (es. settimanale):

    Text Only
    # crontab -e
    0 3 * * 1 /opt/cis-hardening/bin/hardening.sh --audit-all 2>&1 | tee /var/log/cis-audit-$(date +\%Y\%m\%d).log
    
  • Rif. NIS2: Art. 21(2)(a)(e)(f) — gestione rischi, sicurezza manutenzione, valutazione efficacia misure

5. Crittografia Storage

  • Architettura crittografica implementata:
    Doppio layer di cifratura con unlock manuale separato per massima sicurezza:

    Layer Tecnologia Cosa protegge Unlock
    1. LUKS (dm-crypt) AES-256 su /dev/md1 OS, log, config, swap Passphrase al boot via console KVM/IPMI
    2. ZFS Native Encryption AES-256-GCM su rpool/data VM e container Passphrase via SSH dopo boot (zfs load-key)

    Questa separazione garantisce che anche in caso di compromissione dell'OS (layer 1 sbloccato), i dati delle VM restano cifrati finché non viene inserita la seconda passphrase.

  • LUKS:

    • Block device cifrato: /dev/md1 (RAID1 mirror)
    • Unlock: manuale via console KVM/IPMI ad ogni boot — il sistema non parte senza intervento
    • Backup LUKS header: # cryptsetup luksHeaderBackup /dev/md1 --header-backup-file /root/luks-header.bak — custodire off-site
    • ⚠ Perdita della passphrase o del header = dati irrecuperabili
    • ZFS Native Encryption:

    • Dataset cifrato: rpool/data (AES-256-GCM)

    • Unlock post-boot: # zfs load-key rpool/data && zfs mount -a
    • La passphrase ZFS deve essere diversa da quella LUKS
    • Le VM non si avviano finché il dataset non è sbloccato
    • Clevis+Tang (opzione futura per automazione):

    • Permette unlock automatico network-bound: il server si sblocca solo se riesce a contattare un Tang server sulla rete

    • Utile per ridurre il tempo di intervento manuale al reboot
    • Richiede un Tang server affidabile e raggiungibile (es. su un altro datacenter)
    • Non implementato in questa versione del manuale
    • Rif. NIS2: Art. 21(2)(d) — crittografia è esplicitamente richiesta come misura di sicurezza

6. Rete e Segmentazione

  • Architettura di rete:
    • Bridge vmbr0 — management Proxmox (accesso admin, VLAN dedicata o IP OVH principale)
    • Bridge vmbr1 — WAN pfSense (IP failover OVH, MAC virtuale)
    • Bridge vmbr2+ — LAN interne / DMZ (VLAN-tagged o bridge isolati)
  • pfSense VM:
    • Ruolo: default gateway per tutte le VM, NAT, VPN (OpenVPN/WireGuard), IDS/IPS (Suricata/Snort)
    • WAN: IP failover OVH con MAC virtuale assegnato
    • LAN: bridge interno, DHCP per VM se necessario
    • Regole: default deny, whitelist per servizio
    • VPN site-to-site per management remoto (no SSH esposto)
  • Proxmox Firewall (integrato):
    • Livello datacenter: policy globali
    • Livello nodo: protezione host
    • Livello VM/CT: micro-segmentazione (security groups)
    • Abilitare logging delle regole drop/reject
  • Zero Trust overlay (opzionale):
    • Cloudflare Tunnel per accesso web UI senza esporre porte
    • WireGuard mesh per admin access
  • Note NIS2: Art. 21(2)(a)(b) — gestione rischi, segmentazione, controllo accessi rete

7. Autenticazione e Controllo Accessi

  • Proxmox:

    • Realm: LDAP/AD o Proxmox internal (per piccoli setup)

    • RBAC: ruoli minimi necessari (PVEAuditor per monitoring, PVEAdmin solo per admin)

    • Separazione account: no uso di root per operazioni quotidiane

    • API token con least privilege per automazione

    • Strategia 2FA a tre livelli:

      Canale di accesso Utente Autenticazione 2FA
      GUI Proxmox utente admin (es. davide@pam) password TOTP obbligatorio
      GUI Proxmox root@pam password NO — solo emergenza
      SSH utente normale con sudo password TOTP obbligatorio
      SSH root disabilitato (PermitRootLogin no)
      Console KVM/IPMI root password NO — accesso di emergenza, richiede già autenticazione al pannello OVH

      Questa configurazione evita il rischio di lockout totale: se il TOTP smette di funzionare, l'accesso di emergenza via KVM/IPMI resta sempre disponibile.

    • Configurazione 2FA GUI Proxmox (TOTP nativo, niente da installare):

      1. Creare utente admin: Datacenter → Permissions → Users → Add (davide, realm pam)
      2. Assegnare ruolo: Datacenter → Permissions → Add → User Permission → PVEAdmin su /
      3. Attivare 2FA: Datacenter → Permissions → Two Factor → Add → TOTP
      4. Scansionare il QR con Google Authenticator / Authy
      5. Non attivare 2FA su root@pam
        • Configurazione 2FA SSH (libpam-google-authenticator):
      Text Only
      # apt install libpam-google-authenticator -y
      

      Eseguire come l'utente che deve avere il 2FA (NON come root):

      Text Only
      $ google-authenticator
      

      Risposte consigliate:

      • Time-based tokens → y
      • Update .google_authenticator → y
      • Disallow multiple uses → y
      • Rate limiting → y

      Scansionare il QR e salvare i codici di emergenza.

      Configurare PAM — aggiungere in cima a /etc/pam.d/sshd:

      Text Only
      auth required pam_google_authenticator.so nullok
      

      L'opzione nullok consente l'accesso con sola password agli utenti che non hanno ancora configurato l'authenticator. Una volta che tutti gli utenti hanno eseguito google-authenticator, rimuovere nullok per rendere il 2FA obbligatorio:

      Text Only
      auth required pam_google_authenticator.so
      

      Configurare SSH — in /etc/ssh/sshd_config:

      Text Only
      PermitRootLogin no
      KbdInteractiveAuthentication yes
      AuthenticationMethods keyboard-interactive
      

      Questo richiede password + codice OTP per accedere. In futuro è consigliabile aggiungere chiavi SSH per passare a publickey,keyboard-interactive (chiave + OTP = doppio fattore reale).

      Text Only
      # systemctl restart sshd
      

      ⚠ ATTENZIONE: testare da una seconda sessione SSH prima di chiudere quella attiva. In caso di errore, accedere via KVM/IPMI per correggere.

  • pfSense:

    • Admin password forte, 2FA se supportato
    • Accesso solo da LAN management
    • Audit trail: chi ha fatto cosa, quando — log centralizzati (vedi §8)
  • Note NIS2: Art. 21(2)(a)(d)(i)(j) — controllo accessi, autenticazione multi-fattore

8. Logging, Monitoring e SIEM (Wazuh)

  • Wazuh deployment:
    • Opzione A: Wazuh come VM/CT sullo stesso nodo (piccoli setup)
    • Opzione B: Wazuh esterno (consigliato per produzione, evita single point of failure)
    • Componenti: Wazuh Manager + Indexer + Dashboard
  • Agenti Wazuh:
    • Su host Proxmox
    • Su pfSense (via syslog forwarding se agent non supportato)
    • Su ogni VM/CT critica
  • Log da raccogliere:
    • Proxmox: pveproxy, pvedaemon, pvefw, task log, auth log
    • pfSense: firewall log, OpenVPN/WireGuard log, Suricata alerts
    • Sistema: auth.log, syslog, auditd
    • Applicativi: qualsiasi servizio esposto
  • Regole e alerting:
    • Brute force detection
    • File integrity monitoring (FIM)
    • Vulnerability detection (Wazuh built-in)
    • Compliance check (CIS, PCI-DSS, GDPR mappings nativi Wazuh)
  • Retention: minimo 12 mesi (requisito tipico NIS2/GDPR), configurare index rotation
  • Note NIS2: Art. 21(2)(a)(b)(e) — monitoraggio continuo, rilevamento incidenti

9. Backup e Disaster Recovery (PBS)

  • Proxmox Backup Server:
    • Deployment: VM locale (per backup veloci) + replica remota (off-site)
    • Oppure: PBS direttamente su altro server OVH / altra location
    • Encryption: backup cifrati lato client (GCM), encryption key custodita off-site
    • Deduplica e compressione native
  • Policy di backup:
    • VM/CT di produzione: backup giornaliero, retention 30 giorni
    • Config Proxmox (/etc/pve): backup giornaliero separato
    • pfSense config: export XML automatizzato + versioning
    • Wazuh data: snapshot/backup indici
  • RTO/RPO target (da definire col cliente):
    • Esempio: RPO 24h, RTO 4h per ripristino nodo completo
  • Test di restore: procedura documentata, da eseguire minimo trimestralmente
  • DR scenario: perdita totale nodo → procedura rebuild + restore da PBS remoto
  • Note NIS2: Art. 21(2)(c) — continuità operativa, backup, disaster recovery

10. Patch Management

  • Policy:
    • Aggiornamenti sicurezza: entro 72h dalla pubblicazione (critical/high)
    • Aggiornamenti Proxmox: test in finestra di manutenzione, applicare entro 2 settimane
    • Kernel updates: richiedono reboot → pianificare downtime
  • Automazione:
    • unattended-upgrades per security patches Debian
    • Monitoraggio CVE: Wazuh vulnerability detector o feed RSS
    • Script di audit: apt list --upgradable periodico con alerting
  • pfSense: aggiornamento manuale, verificare changelog, backup config pre-update
  • Registro aggiornamenti: log di ogni patch applicata (chi, quando, cosa) — requisito audit
  • Note NIS2: Art. 21(2)(e) — gestione vulnerabilità, aggiornamenti

11. Incident Response

  • Procedura:
    1. Rilevamento (Wazuh alert, segnalazione, anomalia)
    2. Triage e classificazione (severità, impatto)
    3. Contenimento (isolamento VM/rete, snapshot pre-intervento)
    4. Eradicazione e recovery
    5. Post-incident review e lesson learned
  • Obblighi di notifica NIS2 (Art. 23, D.Lgs. 138/2024):
    • Early warning: entro 24h al CSIRT Italia / ACN
    • Notifica completa: entro 72h
    • Report finale: entro 1 mese
  • Contatti:
    • CSIRT Italia: csirt@acn.gov.it
    • ACN portale notifiche: https://www.csirt.gov.it
  • Documentazione: template report incidente (allegato al manuale)
  • Note NIS2: Art. 23 — obblighi di segnalazione

12. Mappatura Controlli NIS2 (Art. 21)

Requisito NIS2 Art. 21(2) Sezione Manuale Stato
(a) Policy analisi rischi e sicurezza §4, §6, §7
(b) Gestione incidenti §8, §11
(c) Continuità operativa e DR §9
(d) Sicurezza supply chain §2 (scelta fornitore OVH)
(e) Sicurezza acquisizione/sviluppo/manutenzione §10
(f) Valutazione efficacia misure §8 (audit Wazuh), §12
(g) Pratiche igiene cyber e formazione Fuori scope (ref. policy org.)
(h) Crittografia §5
(i) Sicurezza risorse umane e controllo accessi §7
(j) Autenticazione multi-fattore §7

13. Checklist di Go-Live

  • Partitioning conforme CIS
  • LUKS + ZFS encryption attivi e testati
  • SSH hardened (key-only, no root, 2FA)
  • Proxmox firewall attivo (datacenter + nodo + VM)
  • pfSense operativo con regole default-deny
  • Wazuh agent attivo su host e VM critiche
  • Backup PBS configurato e primo backup completato
  • Test restore eseguito con successo
  • 2FA attivo per tutti gli account admin
  • IPMI password cambiata e accesso limitato
  • NTP configurato e verificato
  • Log retention configurata (≥12 mesi)
  • Procedura incident response documentata
  • Registro patch management inizializzato

Note e Decisioni Aperte

  • Clevis+Tang per auto-unlock LUKS: includere come opzione avanzata?
  • Template Ansible per automazione deploy: sezione dedicata o allegato?
  • Allegato: template report incidente pre-compilato?
  • Considerare sezione "Evoluzione a cluster" come appendice futura?