This guide covers installation, configuration, and daily use of the openmediavault-zfs plugin.
It assumes OpenMediaVault 8 (OMV8) is already installed and operational.
ZFS (Zettabyte File System) is a mature, enterprise-grade filesystem and logical volume manager originally developed by Sun Microsystems for Solaris and now maintained by the OpenZFS project on Linux. It combines the roles of a traditional filesystem and a volume manager into a single unified layer, which gives it capabilities that older filesystems like ext4 or XFS cannot match.
Copy-on-write with checksums. Every block is checksummed when written and verified when read. If a checksum mismatch is detected (bit rot, failing drive, firmware bug) ZFS knows exactly which block is corrupt. In a redundant pool it can automatically repair the corruption from the good copy without any user intervention.
Snapshots and clones. A snapshot is a read-only, point-in-time copy of a filesystem. It consumes no space at creation — space is only used as data in the original filesystem diverges from the snapshot. Clones are writable copies derived from a snapshot.
Pooled storage. Disks are combined into a pool. One or more filesystems and volumes live inside the pool and share its available space. There are no fixed partition sizes to worry about.
Built-in RAID. RAID is handled by ZFS natively through its VDEV system. No separate hardware RAID controller is required or recommended.
Compression. Transparent, per-dataset compression (LZ4, Zstandard, gzip, etc.) can reduce storage consumption and often increase throughput because less data is written to disk.
Self-healing. When a scrub detects corruption in a redundant pool, ZFS restores the damaged data automatically from the surviving copy.
RAM requirements. ZFS does not require large amounts of RAM to function correctly. It will use available RAM for the Adaptive Replacement Cache (ARC) to speed up reads, but this is a benefit rather than a burden — the ARC is sized dynamically and returns memory to other processes when needed. A system with 4–8 GB of RAM running a home NAS workload is perfectly fine.
ECC memory. ECC RAM is desirable because it prevents the CPU from writing corrupted data to disk in the first place. It is not required — ZFS's checksumming still catches errors that reach storage regardless.
Before creating anything, it helps to understand how ZFS organises storage.
Pool (tank)
├── VDEV 1 — mirror: sda, sdb ← redundancy lives here
├── VDEV 2 — mirror: sdc, sdd ← adding a second VDEV expands capacity
├── [log VDEV] ← optional sync write accelerator (SLOG)
├── [cache VDEV] ← optional read cache (L2ARC)
└── [spare] ← optional hot spare
Datasets inside the pool
├── tank ← pool root (itself a dataset)
├── tank/documents
├── tank/media
│ ├── tank/media/movies
│ └── tank/media/music
└── tank/vm-disks
└── tank/vm-disks/win11 ← a zvol (block device), not a filesystem
A pool is the top-level storage container. It is built from one or more VDEVs.
A VDEV (Virtual Device) is the redundancy unit. The most important rule: if a VDEV fails entirely, the pool is lost. Redundancy protects against individual disk failures within a VDEV, not between VDEVs.
| VDEV type | Redundancy | Min disks | Notes |
|---|---|---|---|
| Basic (stripe) | None | 1 | Any single disk failure loses the pool. Enable copies=2 to get self-healing at the cost of halved capacity. |
| Mirror | 1 copy | 2 | All data exists on every disk. Recommended for most home NAS setups. |
| RAIDZ1 | 1 parity | 3 | Tolerates 1 disk loss. Keep to ≤7 disks per VDEV. |
| RAIDZ2 | 2 parity | 4 | Tolerates 2 disk losses. Keep to ≤11 disks per VDEV. |
| RAIDZ3 | 3 parity | 5 | Tolerates 3 disk losses. Keep to ≤15 disks per VDEV. |
A basic VDEV can be converted to mirror, but a mirror VDEV cannot be converted to a RAIDZ VDEV and RAIDZ1 cannot later become a RAIDZ2 VDEV.
Adding more disks to expand a RAIDZ VDEV is possible via RAIDZ expansion (if the pool has
feature@raidz_expansion active) but this is a slow, one-at-a-time process.
Datasets are the filesystems and volumes that live inside a pool. There are three types:
Datasets inherit properties from their parent unless overridden. Creating a child dataset
tank/media/movies with a different recordsize than tank/media is valid — only the property
on tank/media/movies changes.
Always create at least one named filesystem under the pool and use that for data. The pool root
dataset is typically left with minimal configuration and its mountpoint set to none or /tank.
This keeps administration cleaner and preserves flexibility for property inheritance.
Navigate to Storage → ZFS → Pools.
Click Pool → Add pool. The form fields are:
| Field | Description |
|---|---|
| Name | Pool name. Letters, numbers, hyphens, and underscores. Cannot start with a number. |
| VDEV type | Basic, Mirror, RAIDZ1, RAIDZ2, or RAIDZ3. |
| Devices | Disks to include. The plugin lists unpartitioned, unused disks. |
| Device identification | How disks are identified in the pool: by-id (stable across reboots — recommended), by-path, or dev (e.g. /dev/sda — unstable). |
| Ashift | Sector size hint. Do NOT rely on auto-detection. Set to 12 for modern 4K HDD/SSD. Only go higher if you know otherwise. |
| Force | Pass -f to zpool create. Required if disks have existing partition tables or ZFS labels. |
| Compression | Applied to the pool root dataset and inherited by all children unless overridden. lz4 is an excellent default — fast and space-efficient. |
| Mountpoint | Where the pool root mounts. Defaults to /<poolname>. |
| Case sensitivity | sensitive (Linux default), insensitive, or mixed. Cannot be changed after creation. |
After the pool is created it appears in the table with its health state, size, free space, and fragmentation.
| State | Meaning |
|---|---|
| ONLINE | All devices present and functioning normally. |
| DEGRADED | One or more devices have failed but the pool is still readable/writable. Immediate attention required. |
| FAULTED | The pool is completely unavailable. |
| OFFLINE | The pool has been exported or manually taken offline. |
| REMOVED | A device was physically removed. |
| UNAVAIL | A device cannot be opened. |
Select a pool and use the action menus:
| Action | Description |
|---|---|
| Properties | View and edit ZFS properties on the pool. |
| Details | Raw zpool status -v output showing all devices, error counts, and recent events. |
| History | Chronological log of all ZFS operations performed on the pool. |
| Expand pool | Add a new data VDEV to increase the pool's total capacity. The new VDEV must match the redundancy level you want (adding a mirror VDEV to a mirror pool is common). |
| Clear errors | Reset error counters and clear the pool's error log (zpool clear). Use after replacing a failed device to confirm the new device is error-free. |
| Trim | Send TRIM commands to all SSDs in the pool to reclaim space from deleted data. SSDs only — harmless but ineffective on spinning disks. |
| Upgrade | Enable all supported ZFS feature flags. One-way operation — the pool cannot be imported by an older ZFS version afterward. Only upgrade when all systems that may need to import this pool are running the same or newer ZFS version. |
| Fix packages | Attempt to reinstall or repair corrupted ZFS package installations. |
| Delete | Destroy the pool and wipe labels and filesystem signatures from all member disks. Irreversible. Deletes all data. |
| Action | Description |
|---|---|
| Cache | Add an L2ARC (Level 2 Adaptive Replacement Cache) VDEV using one or more SSDs. Extends the read cache beyond RAM. Most beneficial for workloads with large working sets and random reads. |
| Log | Add a ZIL (ZFS Intent Log) device using an SSD or NVMe. Accelerates synchronous writes. The plugin automatically mirrors the log if two devices are provided to prevent pool loss on log device failure. |
| Spare | Add one or more hot spare disks. If a VDEV member fails, ZFS automatically begins resilver using the spare. |
| Special | Add a special allocation class VDEV for metadata and small blocks. Speeds up metadata operations when backed by fast storage (NVMe). The plugin automatically mirrors the special VDEV when two devices are given. |
| Action | Description |
|---|---|
| Remove vdev | Initiate removal of a VDEV. ZFS evacuates all data from the VDEV to the remaining pool before it is detached. Only certain VDEV types support removal (not RAIDZ). The pool must have enough free space to hold the evacuated data. |
| Cancel removal | Abort an in-progress VDEV removal and restore the VDEV to active use. |
| Removal status | View the current progress of a VDEV removal: bytes remaining, estimated time, and status. |
| Action | Description |
|---|---|
| Offline | Temporarily stop using a device without removing it from the pool. The pool remains healthy (DEGRADED) if it has enough redundancy. Use before a planned maintenance swap. |
| Online | Bring an offlined device back into service. ZFS resilvered any writes that occurred while the device was offline. |
| Attach | Add a device to an existing single-disk (basic) VDEV to convert it into a mirror, or add a disk to an existing mirror to expand it. Add to existing RAIDZ device. |
| Detach | Remove one disk from a mirror, leaving the remaining disk(s) in place. The mirror is downgraded accordingly. |
| Replace | Swap a failed or unwanted device for a new one. ZFS begins resilvering immediately. The pool remains DEGRADED until resilvering completes. |
| Action | Description |
|---|---|
| Start scrub | Begin reading every block in the pool and verifying checksums. Repairs any corruption found using redundant copies. |
| Stop scrub | Abort the current scrub immediately. |
| Pause scrub | Suspend the scrub. Progress is preserved and the scrub can be resumed later. |
| Resume scrub | Continue a paused scrub from where it left off. |
| Scrub status | View detailed scrub progress: bytes scanned, errors found, elapsed time, and estimated completion. |
| Action | Description |
|---|---|
| Import pool | Import a pool that is not currently active. Options: import all available pools, import a specific named pool, or force-import a pool that appears to be in use (e.g. after an unclean shutdown on another system). |
| Export pool | Flush all pending writes, unmount all datasets, and release the pool so it can be moved to another system or safely powered down. |
To replace all disks in a VDEV with larger ones (for example, upgrading from 4 TB to 8 TB drives in a mirror):
zpool status shows scan: resilvered … with 0 errors).autoexpand is enabled by default on new pools.Navigate to Storage → ZFS → Datasets. The table shows all pools, filesystems, volumes, and snapshots in a hierarchy. Use the Type filter at the top to show only filesystems, only snapshots, etc.
Select a pool or parent filesystem and click Add → Add filesystem.
| Field | Description |
|---|---|
| Name | The dataset name component (not the full path). |
| Mountpoint | Where the filesystem mounts. Leave blank to use the default (/<pool>/<name>). Set to none to create an unmounted dataset. |
| Compression | Override the inherited compression algorithm. inherit leaves the parent's setting in place. |
| Record size | The internal block size for this filesystem. Defaults to 128K (good for general use). Use 4K–16K for databases with small random I/O. Use 1M for media files and sequential workloads. |
| Case sensitivity | sensitive, insensitive, or mixed. Set at creation, cannot be changed later. |
After creating a filesystem it can be used as a shared folder target in OMV (Storage → Shared Folders) once registered with Discover → Add new (see Section 13).
Select a pool or parent filesystem and click Add → Add volume.
| Field | Description |
|---|---|
| Name | The dataset name component. |
| Size | Volume size in binary units (e.g. 10G, 500M). |
| Thin provisioning | If checked, the zvol is sparse — it does not reserve all its space upfront. The pool reports the full volume size as used but blocks are only actually allocated as data is written. |
Volumes appear as block devices under /dev/zvol/<pool>/<name>.
Select a filesystem or volume and click Add → Add snapshot.
| Field | Description |
|---|---|
| Name | Snapshot name appended after @ (e.g. before-upgrade). |
| Recursive | Also snapshot all child datasets in one atomic operation. |
Alternatively, Add → Quick snapshot creates a snapshot with an auto-generated
timestamp name (<dataset>@<dataset>-YYYYMMDD-HHMMSS) without prompting.
Add → Quick recursive snapshot does the same recursively.
A clone is a writable filesystem derived from a snapshot.
Select a filesystem and click Clone. The plugin automatically creates a snapshot of the
source dataset (named <source>-clone-base-YYYYMMDD-HHMMSS) and uses it as the clone origin.
The clone initially shares all data blocks with the source and uses no additional space.
Cloned datasets cannot be encrypted independently — they inherit the encryption root of their origin. To create an independent encrypted dataset, promote the clone first.
A clone depends on its origin snapshot — the origin cannot be deleted while the clone exists. Promote reverses this relationship: the clone becomes the independent dataset and the origin becomes dependent on it instead.
Select a clone and click Promote. After promotion the original source dataset becomes the dependent and can be deleted independently.
Select a filesystem or volume and click Rename. The dataset is renamed in ZFS, its mountpoint is updated, and OMV's fstab database is updated to reflect the new path.
Renaming a dataset that has active shared folders is blocked — remove the shares first.
Select any dataset and click Delete. The plugin checks for dependent clones and active shares before proceeding. Snapshots of a filesystem are listed and must be removed (or confirmed) before the parent can be deleted.
For encrypted datasets with auto-unlock configured, always delete through the plugin rather than
via zfs destroy on the command line — the plugin cleans up keyfiles, systemd units, and the
ZFS list cache correctly. See the README for manual cleanup steps if needed.
Storage → ZFS → Snapshots shows all snapshots across all pools with their size, referenced data, creation time, and origin.
Select a snapshot to access:
| Action | Description |
|---|---|
| Rollback | Revert the parent dataset to the state at the time of this snapshot. All data written after the snapshot is permanently discarded. The snapshot itself is preserved. |
| Clone | Create a writable copy derived from this snapshot. |
| Diff | Show which files were created, modified, or deleted between this snapshot and the current state of the dataset (or between two snapshots). Output is presented as a text report. |
| Delete | Remove the snapshot and reclaim its space (only space not referenced by other snapshots or the current dataset). |
| Delete range | Delete a batch of snapshots relative to the selected one: all snapshots earlier than this one, all snapshots later than this one, or all snapshots on the parent dataset with the same prefix. Useful for bulk cleanup. |
ZFS snapshots are accessible in the .zfs/snapshot/<name>/ hidden directory under the
filesystem's mountpoint. For example, if tank/documents is mounted at /tank/documents, the
snapshot tank/documents@2024-01-15 is browsable at:
/tank/documents/.zfs/snapshot/2024-01-15/
No mounting or special tools are needed — simply copy the file back from the snapshot directory.
ZFS native encryption protects dataset contents at rest. The encryption key is required to mount and read a dataset. Without the key the data is unreadable even with physical access to the disks.
Select a pool or parent filesystem and click Add → Add encrypted filesystem.
| Field | Description |
|---|---|
| Name | Dataset name component. |
| Encryption algorithm | AES-128-CCM, AES-192-CCM, AES-256-CCM, AES-128-GCM, AES-192-GCM, or AES-256-GCM. AES-256-GCM is recommended — GCM provides authenticated encryption (detects tampering) and is hardware-accelerated on all modern CPUs. |
| Passphrase | Must be at least 8 characters. Use a strong, unique passphrase. |
| Auto-unlock | Automatically unlock and mount the dataset at boot (stores passphrase in /etc/zfs/keys/). |
| Compression | Compression algorithm (applied before encryption). |
| Record size | Internal block size. |
| Case sensitivity | sensitive, insensitive, or mixed. Set at creation, cannot be changed later. |
| Mountpoint | Where the dataset mounts. |
<note>Note on child datasets: Child filesystems created under an encrypted dataset inherit the encryption and key of their parent. They share the same encryption root and are unlocked and locked together with the parent.</note>
A locked dataset is unmounted and its contents are inaccessible. To lock a dataset, select it and click Encryption → Unload key (lock). To unlock it, click Encryption → Load key (unlock) and enter the passphrase.
Cloned datasets that are not the encryption root cannot be independently locked or unlocked — use the original encryption root instead.
Local auto-unlock stores the passphrase as a file in /etc/zfs/keys/ and configures ZFS to
load the key automatically at boot. This protects against drive theft (an attacker who steals
only the disks cannot read them without the server) but does not protect against someone who
steals the entire server.
Select an encrypted dataset and click Encryption → Enable auto-unlock → Local file. Enter the passphrase to confirm. The plugin:
/etc/zfs/keys/<pool_dataset>.key.keylocation=file:/etc/zfs/keys/<pool_dataset>.key on the dataset.
- Unmasks the zfs-load-key@<instance>.service systemd unit so it runs at boot.
- Writes the dataset path into the ZFS list cache so zfs-mount-generator generates the correct mount unit.
To remove auto-unlock, click Encryption → Disable auto-unlock. The keyfile is deleted,
keylocation is reset to prompt, and the systemd unit is masked so no passphrase prompt
appears at boot (the dataset simply stays locked until manually unlocked).
==== Auto-unlock: remote HTTPS ====
Remote auto-unlock fetches the encryption key from an HTTPS server at boot. The key is never
stored on the local machine. This protects against both drive theft and full server theft —
an attacker cannot decrypt the data without network access to the key server.
Select an encrypted dataset and click Encryption → Enable auto-unlock → Remote HTTPS.
^ Field ^ Description ^
| Key URL | Full HTTPS URL where the key material is served. Must begin with https:. || Skip certificate verification | Disable TLS certificate validation. Use only with self-signed certificates on a trusted network. |
| Decryption passphrase | If the key file at the URL is OpenSSL-encrypted, provide the passphrase to decrypt it. Leave blank if the URL serves the raw key directly. |
| Network timeout | How long (in seconds) to wait for the key server before giving up. Range 10–600, default 60. Allow enough time for the network interface to come up. |
The zfs-remote-unlock service runs at boot, fetches the key, and loads it before the ZFS
mount units start.
Select an encrypted dataset and click Encryption → Change encryption key. Enter the current passphrase and the new passphrase. The key change applies to the encryption root; all child datasets sharing the root are automatically covered.
Navigate to Storage → ZFS → Snapshot Jobs.
Snapshot jobs run omv-zfs-snapshot on a schedule to create snapshots automatically and prune
old ones according to your retention policy.
Click Add to open the form.
| Field | Description |
|---|---|
| Enabled | Toggle the job on or off without deleting it. |
| Dataset | The dataset to snapshot. |
| Snapshot prefix | A label prepended to every snapshot name. Pattern: alphanumeric, hyphens, underscores. Snapshots are named <prefix>-YYYYMMDD-HHMMSS. Default: auto. The prefix must be unique per dataset if multiple jobs target the same dataset. |
| Keep | How many or how long to retain snapshots (see below). |
| Retention unit | Snapshots (count), Days, Weeks, Months, or Years. |
| Recursive | Snapshot this dataset and all its children in one atomic operation. Retention counting is done at the parent level only — child snapshots with the same name are pruned when the parent generation is pruned. |
Keep remain.Keep units ago. For example, Keep=30, Days deletes snapshots older than 30 days.| Field | Description |
|---|---|
| Time of execution | Exactly (cron expression), Hourly, Daily, Weekly, Monthly, Yearly, or At reboot. |
| Minute/Hour/Day/Month/Day of week | Available when Exactly is selected. Accepts * or a comma-separated list of values. The “Every N” checkboxes convert a single value into a */N cron expression. |
| Field | Description |
|---|---|
| Send output via email | Email the job output (stdout + stderr) to root on completion. Requires a working mail relay configured in OMV (System → Notification). |
| Send email on error only | Only send an email if the job exits with a non-zero status. Suppresses routine success emails. |
| Comment | Appended to the email subject line to help identify the job. |
Select a job in the table and click Run. The job executes immediately in the background. Check Storage → ZFS → Logs → ZFS Snapshot to see the output.
Navigate to Storage → ZFS → Scrub Jobs.
Scrub jobs run zpool scrub on a schedule to periodically verify pool integrity. The scrub
reads every block, checks its checksum, and repairs any corruption it finds using redundant
copies. Regular scrubbing is the primary mechanism for detecting and correcting silent
corruption before it spreads.
<note important>Important: A scrub job starts the scrub and exits immediately. The actual scrub runs
asynchronously in the background and may take hours on a large pool. Monitor progress via
Pool → Scrub → Scrub status or zpool status in the shell.</note>
| Field | Description |
|---|---|
| Enabled | Toggle the job on or off. |
| Pool | The pool to scrub. |
| Schedule | Same scheduling options as snapshot jobs. Default: Weekly. |
| Send output via email | Email a brief start notification to root. |
| Send email on error only | Only email if the scrub fails to start. |
| Comment | Appended to the email subject. |
Recommended schedule: Monthly is sufficient for healthy pools on consumer hardware. Weekly is appropriate for pools under heavy write load. Scrubbing is I/O-intensive — schedule it during off-peak hours.
Navigate to Storage → ZFS → Replication Jobs.
Replication jobs copy a ZFS dataset (and its snapshots) to another location using zfs send and
zfs receive. Subsequent runs send only the incremental difference since the last replication,
making them efficient even for large datasets. Replication can target a local pool or a remote
host over SSH.
| Field | Description |
|---|---|
| Enabled | Toggle the job on or off. |
| Source dataset | The dataset to replicate. |
| Snapshot prefix | Prefix for replication snapshots. Default: replicate. If using Use existing snapshots, this must exactly match the prefix used by the snapshot job. |
| Recursive | Replicate the dataset and all its children. |
| Raw send | Use zfs send -w to send encrypted data without decrypting it first. The destination receives the data in its encrypted form. Requires the source dataset to be encrypted. The destination does not need to have the key. |
| Use existing snapshots | Instead of creating a new snapshot, find the most recent snapshot matching the prefix and send it. Recommended when a separate snapshot job is already managing snapshots for this dataset. Prevents two jobs from fighting over snapshot creation and avoids breaking the incremental chain. |
| Keep snapshots on source | Number of replication snapshots to retain on the source after a successful send. 0 keeps all snapshots. Ignored when Use existing snapshots is enabled (the snapshot job controls retention instead). |
| Use ZFS bookmarks | After each successful send, create a ZFS bookmark as the incremental base for the next run. Bookmarks survive snapshot deletion, so you can aggressively prune the source while still sending incremental data. Cannot be used with Recursive mode (ZFS limitation). |
| Field | Description |
|---|---|
| Type | Local (same machine, different pool) or Remote (SSH). |
| Destination dataset | Path on the destination where data is received (e.g. backup/replica). The dataset is created on the first run. |
| Remote host | Hostname or IP address of the destination server. Remote only. |
| SSH Certificate | The SSH key pair to authenticate with. Create one under System → Certificates → SSH and copy it to the remote host before creating the replication job. |
| SSH user | Remote user account. Default: root. Non-root users need zfs allow delegation on the destination. |
| SSH port | SSH port on the destination. Default: 22. |
Same scheduling and email options as snapshot and scrub jobs.
Scenario: daily replication with independent snapshot retention
This is the most common setup. A snapshot job manages snapshots on the source; the replication job sends them to the destination without creating its own.
tank/documents with prefix daily, execution Daily, keep 30 Days.tank/documents with prefix daily, execution Daily, Use existing snapshots enabled, Keep snapshots on source = 0, destination backup/documents on a local backup pool.
The snapshot job runs first (or within the same cron minute), then the replication job sends
the newest daily-* snapshot incrementally.
Scenario: self-contained replication with source pruning
When no separate snapshot job exists:
tank/vm-disks with prefix replicate, keep 3 on source, destination on a remote server.The replication job creates its own snapshot, sends it, then prunes old replication snapshots on the source to keep only 3.
Scenario: efficient replication with bookmarks
Suitable when disk space on the source is limited:
tank/photos with prefix weekly, keep 1 Snapshots.tank/photos with prefix weekly, Use existing snapshots enabled, Use ZFS bookmarks enabled.The replication job uses the bookmark from the previous run as its incremental base, so the single retained snapshot is sufficient — there is no need to keep an older snapshot just for the next send.
Before creating a remote replication job:
~/.ssh/authorized_keys on the remote host.The replication script uses strict host key checking — the first connection to a new host is accepted automatically, but subsequent connections reject unknown key changes.
Job output is written to /var/log/omv-zfs-replicate.log and is also viewable in the OMV
web interface under Storage → ZFS → Logs → ZFS Replicate.
ZFS properties control the behaviour of pools and datasets. They can be inherited from a parent
(shown as source inherited) or set explicitly on a dataset (source local).
Select any pool, filesystem, volume, or snapshot and click Properties. The table shows every property, its current value, its source, and whether it can be edited. Click the edit icon on a row to change a property's value.
Custom user-defined properties (in namespace:name format) can also be added.
| Property | Values | Notes |
|---|---|---|
compression | off, lz4, zstd, gzip, lzjb, zle | lz4 is fast and effective for most data. zstd offers better compression ratios for archival data at some CPU cost. Already-compressed files (video, ZIP, JPEG) do not compress further. |
recordsize | 4K–1M | The internal block size. Larger values suit sequential workloads; smaller values suit databases with random I/O. Default 128K. |
atime | on, off | Whether to update access time when files are read. off reduces write amplification significantly on read-heavy datasets. |
copies | 1, 2, 3 | Number of copies of each block. Setting copies=2 on a non-redundant (basic) VDEV gives self-healing capability at the cost of halved usable capacity. |
quota | e.g. 100G | Maximum space this dataset and all its children can use. |
refquota | e.g. 100G | Maximum space this dataset alone can use (excluding children). |
reservation | e.g. 50G | Guaranteed space reserved for this dataset and its children. |
dedup | on, off | Block-level deduplication. Requires roughly 5 GB of RAM per TB of data for the dedup table. Generally not recommended for home NAS unless data is extremely repetitive. |
sync | standard, always, disabled | Controls when writes are committed to disk. always is safest but slowest. disabled is fastest but risks data loss on power failure. |
snapdir | hidden, visible | Whether .zfs/snapshot/ is visible in directory listings. visible makes snapshot access easier for users. |
readonly | on, off | Prevent writes to the dataset. |
Select a dataset and click Details to see the raw output of zpool status -v (for pools) or
zfs get all (for filesystems, volumes, and snapshots). This is useful for debugging or checking
the exact value of any property without the filtered view.
ZFS filesystems must be registered in OMV's internal database before they can be used as shared folder targets. Discovery synchronises OMV's fstab database with the live ZFS state.
This is accessible from both the Pools table and the Datasets table under Discover.
| Action | Description |
|---|---|
| Add new | Find any ZFS filesystems that exist in ZFS but are not yet in OMV's database, and register them. Use this after creating a new dataset that you want to share. |
| Add new + delete missing | Full bidirectional sync: adds unregistered datasets and removes stale entries for datasets that no longer exist. |
| Delete missing | Remove OMV fstab entries for datasets that have been deleted from ZFS but whose entries still remain in the database. |
<note>Note: The plugin backs up config.xml before every discovery operation. The 20 most
recent backups are kept at /etc/openmediavault/config.xml.<timestamp>.</note>
<note>Locked encrypted datasets are never removed by Delete missing — the plugin recognises that a dataset may simply be locked rather than deleted.</note>
The plugin adds four dashboard widgets. Enable them via Dashboard → Configure widgets (the gear icon on the dashboard).
| Widget | Description |
|---|---|
| Pool Health | A table showing the health status of every pool (ONLINE, DEGRADED, FAULTED, etc.). |
| Pool Status | A compact table showing each pool's health, capacity percentage, and used/available space. |
| ARC Size | A single number showing the current total ARC (Adaptive Replacement Cache) size. |
| ZFS ARC Hit/Misses | The ratio of total hits to misses. A hit ratio above 90% indicates the cache is effective for your workload. |
Navigate to Storage → ZFS → ARC Stats for a full text dump of ARC internals: total size,
MRU/MFU cache sizes, hit/miss counters, prefetch statistics, and more. This is the same output
as the arc_summary/zarcsummary command-line tool.
Five log viewers are available under Storage → ZFS → Logs:
| Log | Contents |
|---|---|
| ZFS Events | Output from the ZFS Event Daemon (ZED). Includes pool state changes, device errors, scrub completions, and resilver events. Monitor this for health alerts. |
| ZFS Snapshot | Output from all snapshot job runs (/var/log/omv-zfs-snapshot.log). |
| ZFS Scrub | Output from all scrub job runs (/var/log/omv-zfs-scrub.log). |
| ZFS Replicate | Output from all replication job runs (/var/log/omv-zfs-replicate.log). |
| ZFS Remote Unlock | Output from the remote HTTPS key-fetch service (zfs-remote-unlock). Useful for diagnosing boot-time failures when a remote auto-unlock is configured. |
Navigate to Storage → ZFS → Settings.
This page controls system-level ZFS tuning that applies globally, independent of any individual pool or dataset.
| Field | Description |
|---|---|
| Maximum ARC size (MiB) | Hard ceiling on how much RAM the Adaptive Replacement Cache may use. Set to 0 for no limit (ZFS default — ARC will use up to roughly half of installed RAM at steady state). A typical explicit value is 50% of installed RAM (e.g. 16384 for a 32 GiB system). |
| Minimum ARC size (MiB) | The floor the ARC will not shrink below even under memory pressure. Set to 0 to use the ZFS default. Raising this prevents other processes from evicting the cache entirely on a RAM-constrained system. |
Changes are written to /etc/modprobe.d/zfs.conf and take effect after a reboot or after reloading the ZFS module.
Designing a ZFS pool layout is about balancing performance, redundancy, capacity, and future flexibility. Decisions made up front may be hard to change later, so plan carefully.
The optimum pool layout depends on how the data will be used. For sequential workloads (media, backups, archive) RAIDZ works well, but prefer RAIDZ2 for larger drives to reduce resilver second-failure risk. For random I/O (containers, VMs, databases) use mirrors — they offer the best combination of read performance (spread across disks), write performance, and faster resilver after disk replacement.
Do not add optional devices (log, cache, and/or special VDEV) without justification and understanding. For example, a “log device” is useless on a home NAS which does not generate sync writes (SMB shares do not, NFS shares do). Analyse first, but the answer to improving pool performance may simply be to add RAM.
For a mix of SSDs and HDDs, consider using the SSDs in a mirror pool and the HDDs in a separate RAIDZ pool. In a home NAS this separation is preferable to trying to enhance RAIDZ performance by using a log, cache, and/or special VDEV, which only adds complexity and cost (typical consumer SSD/NVMe devices are not suitable for these optional VDEVs).
Beware adding a basic VDEV to an existing mirror/RAIDZ pool. This turns a pool into a stripe, where losing a single drive can lose the entire pool.
by-id device identification. Device names like /dev/sda can change after a reboot if drives are added or removed. Stable by-id paths ensure ZFS always finds the right disk.lz4 is essentially free — it is so fast that on most systems it improves throughput even for data that compresses modestly.recordsize, compression, and quotas independently.recordsize=1M for media libraries (movies, music, photos). Sequential reads of large files benefit enormously from large record sizes.recordsize=4K or 8K for database files (PostgreSQL, MySQL, SQLite). These databases do their own internal block management and need ZFS's blocks to match.atime on busy datasets. Every file read normally triggers a metadata write to update the access time. atime=off eliminates this overhead.daily, weekly, monthly rather than auto when running multiple snapshot jobs per dataset at different frequencies.zpool status after each scrub. Any errors reported warrant investigation.zfs destroy. The plugin cleans up keyfiles, systemd units, and the ZFS list cache. A bare zfs destroy leaves orphaned artifacts.Use existing snapshots rather than letting the replication job manage its own snapshots. This gives you independent control over local snapshot retention and avoids conflicts if you run multiple replication jobs for the same dataset.You can use the documentation written for OMV7 as a reference as well but some things may be out of date.
Go to → ZFS Plugin For OMV7