Introduction
If you installed Proxmox VE on a single boot drive and now have two or three extra disks sitting idle in the case, ZFS is probably the reason you keep hearing that name. It's the storage option Proxmox nudges you toward during install, and for good reason — it does things ext4 and plain LVM just can't: it catches silently corrupted data, it snapshots a VM in under a second, and it can mirror your disks without a hardware RAID card. None of that happens automatically, though. You still have to build the pool and tell Proxmox to use it.
This guide walks through that process end to end — from picking the right disks to actually storing a VM's virtual disk on your new ZFS pool. It works the same on Proxmox VE 8.x and 9.x, since the ZFS integration hasn't changed in any meaningful way between those releases.
What You Will Learn
By the end of this you'll have a working ZFS pool built from spare disks, added as usable storage inside Proxmox, and ready to hold VM disks, container volumes, ISOs, or backups.
- What ZFS actually is, in plain terms, and why Proxmox leans on it so heavily
- How to identify your spare disks safely, using their stable
by-idnames - How to build a pool through the Proxmox GUI and through the command line
- The difference between a mirror and a RAIDZ pool, and which one to pick
- How to add that pool as storage so it shows up when you create a new VM
- The mistakes that trip up almost everyone doing this for the first time
What Is This Feature?
ZFS is a filesystem and volume manager rolled into one. On a normal Linux setup you'd have a separate partitioning tool, a separate RAID layer (mdadm), and a separate filesystem (ext4) stacked on top of each other. ZFS collapses all three into a single system that knows about your actual disks, not just abstract blocks.
That matters for a hypervisor because ZFS gives you three things at once that would otherwise need separate tools:
- Checksums on every block. ZFS knows when data has quietly rotted on disk — something ext4 has no way to detect — and can repair it automatically if you gave it a mirror or RAIDZ pool.
- Instant snapshots. Because ZFS is copy-on-write, taking a snapshot doesn't copy anything. It just marks a point in time and starts tracking changes from there, which is why Proxmox can snapshot a running VM in a second or two.
- Software RAID without a card. A mirror or RAIDZ pool spans multiple physical disks and survives a drive failure, and you get this for free — no battery-backed RAID controller needed.
A "pool" in ZFS terms is just the collection of disks you group together — you name it once (people commonly call it tank or rpool, though any name works), and from that point on Proxmox treats it as a single chunk of storage.
Why Would You Use It?
The honest answer: because it's already there. If you installed Proxmox VE with ZFS as the root filesystem, the kernel modules and tooling are present with zero extra packages. Turning a couple of spare disks into usable VM storage takes about ten minutes, and you don't need to buy a RAID card or configure mdadm by hand.
It's also the difference between finding out about a failing drive from a SMART alert next month, versus finding out because a VM's disk image is subtly corrupted and you don't know until you try to restore from a backup that copied the corruption along with it. ZFS's checksumming catches that kind of failure while it's still just a checksum mismatch, not a ruined VM.
I'd only skip ZFS if you're working with a single small SSD and no room to spare — a mirror needs at least two disks, and RAIDZ needs at least three. If you've genuinely only got one extra drive, plain LVM-thin is a reasonable fallback, just without the self-healing.
Prerequisites
Before you start, make sure you actually have this in place:
- A working Proxmox VE 8.x or 9.x install, reachable through the web GUI on port 8006
- One or more spare disks not already in use — a single disk for a basic pool, two for a mirror, three or more for RAIDZ1
- Root or a user with
Sys.ModifyandDatastore.Allocatepermissions, if you're not using the root account - SSH access to the node, or comfort using the built-in Shell button in the GUI, if you plan to use the CLI method
One thing to check ahead of time: the disks you're about to use should be completely empty — no existing partitions, no data you care about. Creating a pool will wipe whatever is on them.
Step-by-Step Tutorial
Step 1: Find your spare disks
Log in to the Proxmox web GUI, click your node in the left-hand tree, then open Disks. You'll see every physical disk attached to the server, along with its size, model, and whether it's already in use. Confirm the disks you plan to use show up as unused before going further.
If you'd rather check from the command line:
lsblk
ls -la /dev/disk/by-id/
That second command matters more than it looks. Device names like /dev/sdb can shift around after a reboot if disks are added or removed, but the by-id names are tied to the drive's actual serial number and never change. Always build your pool using those, not /dev/sdX.
Step 2 (GUI method): Create the pool
Still under your node, go to Disks > ZFS and click Create: ZFS. A dialog opens with a few fields:
- Name — whatever you want to call the pool, e.g.
tank - RAID Level — Single, Mirror, RAID10, RAIDZ, RAIDZ2, or RAIDZ3
- Compression — leave this on
lz4, the default - ashift — leave at 12 unless you specifically know your drives use a different sector size
- Disks — checkboxes for each available disk to include
Pick your RAID level, check the disks you want in the pool, and click Create. Proxmox builds the pool and — this is the part people don't expect — automatically registers it as storage too, so you won't need a separate step to make it usable.
Step 2 (CLI method): Create the pool by hand
If you'd rather do this over SSH, here's the same thing as a command. For a mirror across two disks:
zpool create -o ashift=12 tank mirror \
/dev/disk/by-id/ata-DISK1-serial \
/dev/disk/by-id/ata-DISK2-serial
For three or more disks with single-drive-failure tolerance, use RAIDZ1 instead:
zpool create -o ashift=12 tank raidz1 \
/dev/disk/by-id/ata-DISK1-serial \
/dev/disk/by-id/ata-DISK2-serial \
/dev/disk/by-id/ata-DISK3-serial
Turn on compression right after creating the pool — it isn't retroactive, so data written before this point stays uncompressed:
zfs set compression=lz4 tank
Building it by hand doesn't register it as Proxmox storage automatically the way the GUI does, so there's one more step below.
Step 3: Add the pool as Proxmox storage
If you used the GUI in Step 2, this already happened — skip ahead. If you built the pool from the CLI, go to Datacenter > Storage > Add > ZFS. Fill in:
- ID — a storage name Proxmox will show you in menus, e.g.
tank-storage - ZFS Pool — select
tankfrom the dropdown (Proxmox scans for existing pools automatically) - Content — tick Disk image and Container at minimum
- Nodes — leave as "All" unless this pool only exists on one node in a cluster
You can do the same thing from the shell:
pvesm add zfspool tank-storage --pool tank --content images,rootdir
Step 4: Confirm it works
Go create a new VM, and on the Disks tab, check the Storage dropdown. Your new pool should be listed. Select it, finish creating the VM, and boot it — the virtual disk now lives on ZFS.
You can also confirm from the command line:
zpool status tank
pvesm status
The first command shows pool health (it should say ONLINE with no errors). The second lists every storage backend Proxmox knows about, including your new one, with free space and usage.
Commands Explained
| Command | What it does |
|---|---|
lsblk | Lists block devices attached to the system, so you can see which disks are which before touching anything. |
ls -la /dev/disk/by-id/ | Shows the stable, serial-number-based names for each disk — use these instead of /dev/sdX when building a pool. |
zpool create -o ashift=12 tank mirror disk1 disk2 | Builds a new ZFS pool named tank as a mirror across two disks, with the block size hint set to 4K sectors. |
zfs set compression=lz4 tank | Turns on lz4 compression for everything written to the pool from this point forward. |
pvesm add zfspool tank-storage --pool tank --content images,rootdir | Registers an existing ZFS pool as a Proxmox storage entry, usable for VM disks and container volumes. |
zpool status tank | Reports the health of the pool and each disk in it — the first place to look if something seems off. |
pvesm status | Lists all configured storage on the node, including type, total size, and free space. |
Common Errors
A few messages come up often enough that it's worth knowing them before you hit them yourself.
cannot create 'tank': pool already exists
You (or a previous install) already created a pool with that name. Either pick a different name or destroy the old one first with zpool destroy tank — only do that if you're certain nothing important is on it.
/dev/sdb is part of exported pool 'tank'
ZFS found leftover pool metadata on a disk from a previous setup. Wipe it with zpool labelclear /dev/sdb, or add -f to your zpool create command to force past the warning, once you've confirmed the disk truly is safe to reuse.
insufficient replicas
This shows up in zpool status when a disk in a mirror or RAIDZ set has failed or disconnected. Reseat the drive if it's a cabling issue, or replace it with zpool replace tank old-disk new-disk.
Troubleshooting
If the pool doesn't show up as a storage option when creating a VM, double check that you actually ticked Disk image under Content when adding the storage — it's easy to add the storage entry and forget that checkbox, and Proxmox won't complain, it'll just quietly not offer it where you expect.
If zpool create refuses to run and complains the disk is in use, something still has a partition table or is mounted. Run wipefs -a /dev/sdX on the disk (using its actual by-id path) after triple-checking it's the right one, then try again.
If performance feels slower than expected on spinning disks, that's usually normal ZFS behavior rather than a misconfiguration — random I/O on RAIDZ across HDDs is genuinely slower than a single disk would be for that workload. Mirrors handle random I/O noticeably better than RAIDZ if that's the bottleneck you're hitting, and there's a reason NAS builds default to mirrors for VM storage.
Best Practices
Stick to mirrors, not RAIDZ, if the pool is going to hold VM disks. RAIDZ is great for bulk storage like backups or media, but VM disk I/O is mostly small, random reads and writes, and that's exactly the pattern RAIDZ handles worst. A pair of mirrors striped together (what Proxmox calls RAID10 in the GUI) scales both capacity and performance better as you add disks.
Don't mix disk sizes or speeds in the same vdev if you can help it — ZFS will size the pool to the smallest disk in the set, so pairing a 4TB drive with a 1TB drive wastes 3TB of the larger one.
Leave ashift at 12 unless you have a specific reason not to. It can't be changed after the pool is created, and getting it wrong on modern 4K-sector drives tanks performance permanently — you'd have to destroy and rebuild the pool to fix it.
As of Proxmox VE 8.1 and later, ZFS's ARC memory cache defaults to 10% of system RAM, capped at 16 GiB, which is far more reasonable than the older 50%-of-RAM default. On a dedicated storage node you can still raise that if you have RAM to spare, but on a typical homelab box the current default rarely needs touching.
Frequently Asked Questions
Do I need ECC RAM to use ZFS?
No. ECC RAM reduces the (already small) risk of memory errors corrupting data before ZFS checksums it, but plenty of homelabs run ZFS on non-ECC hardware without issue. It's a nice-to-have, not a requirement.
Can I add more disks to a pool later?
You can add a whole new mirror or RAIDZ set alongside your existing one to grow capacity, but you generally can't add a single disk to an existing RAIDZ group after the fact. Plan your disk count up front if you can.
What's the difference between a mirror and RAID1?
Functionally similar — both write the same data to two disks — but ZFS's mirror also checksums every block and can self-heal corruption during a scrub, which traditional RAID1 can't do.
Will this work for my Proxmox boot drive too?
This guide covers adding a second pool for extra storage. If ZFS is already your root filesystem, it was set up during install and doesn't need this process — that's a separate pool, usually named rpool.
Can I use this pool for backups instead of VM disks?
Yes — just tick VZDump backup file under Content when adding the storage, in addition to or instead of Disk image and Container, depending on what you want the pool used for.
Conclusion
Once the pool exists, it mostly runs itself. Run an occasional zpool scrub tank — monthly is plenty for a homelab — and keep an eye on zpool status after any hardware changes. The setup takes ten minutes; the payoff is storage that tells you when something's actually wrong instead of quietly failing until a restore doesn't work.