Installing Proxmox VE and Configuring Storage

This is part of Installing a Data Processor in Proxmox VE (Cluster).

Install Proxmox VE

Refer to the Proxmox VE Installation documentation for detailed instructions. The following configuration was used for this deployment:

  • Proxmox VE installed on two 480 GB SSDs in a ZFS RAID1 mirror (rpool) — boot and OS only, no VM storage.
  • Management interface on the first 1 GbE NIC, configured with a static IP.

Confirm the installation before proceeding:

pveversion
zpool status rpool
ip -br a

Example output:

root@pve:/# pveversion
pve-manager/9.2.2/b9984c6d90a4bd80 (running kernel: 7.0.2-6-pve)
root@pve:/# zpool status rpool
  pool: rpool
 state: ONLINE
config:
        NAME                                    STATE     READ WRITE CKSUM
        rpool                                   ONLINE       0     0     0
          mirror-0                              ONLINE       0     0     0
            ata-MTFDDAV480TDS_21303076C5E7-part3 ONLINE     0     0     0
            ata-MTFDDAV480TDS_21303076C684-part3 ONLINE     0     0     0
errors: No known data errors
root@pve:/# ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128
vmbr0            UP             10.20.0.231/24 fe80::7aac:44ff:fe63:eef0/64
root@pve:/#

Configure Storage

Stellar Cyber recommends one storage target with sufficient capacity for the VM system disks and a second, dedicated storage target for the Data Lake's Elasticsearch data. Separating the two ensures that Elasticsearch data growth can never consume the space needed by the VM system disks, and confines a data-disk failure to the data pool — the DL and DA virtual machines remain bootable and recoverable.

This deployment uses three ZFS pools:

Pool

Devices

Layout

Purpose

rpool

2 × 480 GB SSD

RAID1 mirror

Proxmox VE OS (created by installer)

vmstore

1 × 1.92 TB SSD

Single disk

DL and DA VM system disks

datalake

7 × 1.92 TB SSD

Stripe

Data Lake Elasticsearch data

A striped pool provides maximum capacity and throughput with no redundancy, matching Stellar Cyber's standard capacity-first Data Lake storage model. A failure of any disk in this pool destroys the Elasticsearch data but does not affect the VM system disks on vmstore — the DL and DA virtual machines remain bootable, and recovery consists of rebuilding the pool and re-adding the data disk.

Identify the Disks

Always reference disks by their /dev/disk/by-id/ path rather than /dev/sdX. Kernel device letters are assigned in discovery order and can change between reboots; the by-id path is tied to the disk's model and serial number and is stable.

ls -l /dev/disk/by-id/ | grep -v part

Record the eight data disk IDs. Exclude the two disks used by rpool.

root@pve:/# ls -l /dev/disk/by-id/ | grep -v part
total 0
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MTFDDAV480TDS_21303076C5E7 -> ../../sdi
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MTFDDAV480TDS_21303076C684 -> ../../sdj
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MZ7LH1T9HALT0D3_S5YXNA0R801296 -> ../../sdg
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MZ7LH1T9HALT0D3_S5YXNA0R801301 -> ../../sde
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MZ7LH1T9HALT0D3_S5YXNA0R801302 -> ../../sdb
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MZ7LH1T9HALT0D3_S5YXNA0R801303 -> ../../sdf
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MZ7LH1T9HALT0D3_S5YXNA0R801306 -> ../../sdc
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MZ7LH1T9HALT0D3_S5YXNA0R801312 -> ../../sdh
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MZ7LH1T9HALT0D3_S5YXNA0R801313 -> ../../sda
lrwxrwxrwx 1 root root 9 Jul 15 17:49 ata-MZ7LH1T9HALT0D3_S5YXNA0R801316 -> ../../sdd
root@pve:/#

Prepare the Disks

Disks that previously belonged to another system carry partition tables or filesystem signatures that prevent pool creation. Clear each of the eight data disks.

This is irreversible and there is no undo. Before running these commands, confirm each by-id name is one of your eight data disks and is not one of the two rpool disks identified above. In this example, rpool uses the two MTFDDAV480TDS disks; the eight MZ7LH1T9HALT0D3 disks are the data disks.

Run the following three commands against each data disk. Substitute your own by-id names:

wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801313
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801313
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801313

wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801296
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801296
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801296

wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801301
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801301
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801301

wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801302
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801302
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801302

wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801303
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801303
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801303

wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801306
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801306
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801306

wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801312
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801312
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801312

wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801316
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801316
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801316

Command

Purpose

wipefs -a

Removes filesystem and partition-table signatures. This is what allows zpool create to proceed.

sgdisk --zap-all

Destroys both the primary GPT and the backup GPT at the end of the disk.

blkdiscard -f

Issues a full TRIM, returning the SSD to a clean state. Recommended on repurposed hardware, but not required for pool creation.

wipefs may report nothing on a disk that is already clean; sgdisk will still report that GPT data structures were destroyed. Both outcomes are normal.

Example output for one disk:

root@pve:/# wipefs -a /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801313
sgdisk --zap-all /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801313
blkdiscard -f /dev/disk/by-id/ata-MZ7LH1T9HALT0D3_S5YXNA0R801313
Creating new GPT entries in memory.
GPT data structures destroyed! You may now partition the disk using fdisk or
other utilities.
blkdiscard: Operation forced, data will be lost!
root@pve:/#

Create the Storage Pools

# VM system disk pool -- one disk
zpool create -o ashift=12 -o autotrim=on -O compression=lz4 -O atime=off vmstore ata-MZ7LH1T9HALT0D3_S5YXNA0R801313

# Data Lake data pool -- striped across the remaining seven disks
zpool create -o ashift=12 -o autotrim=on -O compression=lz4 -O atime=off datalake \
  ata-MZ7LH1T9HALT0D3_S5YXNA0R801296 ata-MZ7LH1T9HALT0D3_S5YXNA0R801301 \
  ata-MZ7LH1T9HALT0D3_S5YXNA0R801302 ata-MZ7LH1T9HALT0D3_S5YXNA0R801303 \
  ata-MZ7LH1T9HALT0D3_S5YXNA0R801306 ata-MZ7LH1T9HALT0D3_S5YXNA0R801312 \
  ata-MZ7LH1T9HALT0D3_S5YXNA0R801316

Listing devices with no mirror or raidz keyword creates a stripe — each disk becomes its own vdev and ZFS stripes data across all of them.

Settings and rationale:

Setting

Value

Why

ashift

12

4K sector alignment, correct for all modern SSDs.

autotrim

on

Returns freed blocks to the SSD automatically.

compression

lz4

Early-abort algorithm — negligible CPU cost, never slower on incompressible data. Elasticsearch compresses its own data, so expect a modest ratio (~1.1–1.2×) rather than the higher figures quoted for OS disks.

atime

off

Removes a metadata write on every read.

Pool creation must be performed from the command line. The Proxmox VE web interface does not provide a striped option — its RAID Level dropdown offers only Single Disk, Mirror, RAID10, RAIDZ, RAIDZ2, RAIDZ3, and dRAID variants, and Single Disk accepts exactly one device (selecting more returns please give only one disk for single disk mode).

Register the Pools with Proxmox

pvesm add zfspool vmstore --pool vmstore --content images,rootdir
pvesm add zfspool datalake --pool datalake --content images,rootdir

Omitting --sparse satisfies Stellar Cyber's thick provisioning requirement: zvols created on these storages carry a full reservation and cannot oversubscribe the pool.

Verify

zpool status vmstore datalake
zpool list
pvesm status

zpool status should list vmstore with one device, and datalake with all seven disks as individual vdevs — each ONLINE, with no mirror-N or raidz-N groupings.

root@pve:/# zpool status vmstore datalake
  pool: datalake
 state: ONLINE
config:
        NAME                                  STATE     READ WRITE CKSUM
        datalake                              ONLINE       0     0     0
          ata-MZ7LH1T9HALT0D3_S5YXNA0R801296  ONLINE       0     0     0
          ata-MZ7LH1T9HALT0D3_S5YXNA0R801301  ONLINE       0     0     0
          ata-MZ7LH1T9HALT0D3_S5YXNA0R801302  ONLINE       0     0     0
          ata-MZ7LH1T9HALT0D3_S5YXNA0R801303  ONLINE       0     0     0
          ata-MZ7LH1T9HALT0D3_S5YXNA0R801306  ONLINE       0     0     0
          ata-MZ7LH1T9HALT0D3_S5YXNA0R801312  ONLINE       0     0     0
          ata-MZ7LH1T9HALT0D3_S5YXNA0R801316  ONLINE       0     0     0
errors: No known data errors
  pool: vmstore
 state: ONLINE
config:
        NAME                                  STATE     READ WRITE CKSUM
        vmstore                               ONLINE       0     0     0
          ata-MZ7LH1T9HALT0D3_S5YXNA0R801313  ONLINE       0     0     0
errors: No known data errors
NAME       SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
datalake  12.1T   552K  12.1T        -         -     0%     0%  1.00x    ONLINE  -
rpool      444G  2.05G   442G        -         -     0%     0%  1.00x    ONLINE  -
vmstore   1.73T   432K  1.73T        -         -     0%     0%  1.00x    ONLINE  -
Name       Type       Status    Total (KiB)   Used (KiB)  Available (KiB)   %
datalake   zfspool    active    12851347456          552      12851346904  0.00%
local      dir        active      449000960          128        449000832  0.00%
local-zfs  zfspool    active      449001044           96        449000948  0.00%
vmstore    zfspool    active     1804599296          432       1804598864  0.00%
root@pve:/#