Safeguard
Supply Chain Security•

Home NAS Explained: ZFS, RAID Levels, Snapshots and Backups

A home NAS keeps files on redundant disks, but RAID is not a backup. Learn ZFS mirrors and RAIDZ, scrubs, snapshots, replication and the 3-2-1 rule.

Safeguard Security Team
51 min read

A home NAS (network attached storage) is an always-on computer that stores files on several disks and shares them over your network. For a homelab, use ZFS: mirrors or RAIDZ for redundancy, scrubs against silent corruption, snapshots for undo, and replication for backups. Redundancy survives a dead disk; only separate, offline, tested copies survive ransomware and fire.

This guide goes one level deeper than our walkthrough on how to build a tiny data center at home. We read the OpenZFS documentation and the zpool and zfs man pages published at openzfs.github.io, the Linux kernel md RAID documentation, the smartctl, smb.conf and exports man pages, CISA's #StopRansomware Guide and its earlier Data Backup Options paper, and NIST SP 800-209, Security Guidelines for Storage Infrastructure. Every command, property name and default below comes from those sources. Commercial NAS appliances are described here by category only.

Key takeaways

  • RAID and ZFS redundancy are about availability. They keep the pool online when a disk fails. They do not protect you from an accidental rm, an encrypted share or a house fire. A backup is a separate copy on separate hardware.
  • ZFS checksums every block and stores the checksum in the parent block pointer. On a mirror or RAIDZ vdev, a block that fails its checksum on one disk is rebuilt from the good copy or from parity and rewritten. A scrub reads every block in the pool to find those errors before you need the data.
  • Usable capacity is roughly (N minus P) times disk size for RAIDZ and one disk's size for each mirror. Worked examples below show how 4, 6 and 8 disks of 12 TB come out under each layout.
  • The OpenZFS hardware page highly recommends ECC memory, says hardware RAID controllers should not be used with ZFS, and says drive managed SMR disks are not recommended for ZFS pools. Use a plain HBA and CMR drives.
  • Snapshots are cheap and instant, but they live in the same pool. Pair them with zfs send replication to a second machine that pulls the data with its own credentials, and with one copy that is offline. That is the 3-2-1 rule: three copies, two media types, one off site.
  • Always build pools with /dev/disk/by-id/ paths, dry run zpool create -n first, and confirm the exact device before any command that wipes or labels a disk.
  • Never expose SMB or NFS to the internet. Share on the LAN with SMB3 signing or encryption, or NFSv4 with Kerberos, and reach the NAS from outside only over a VPN.
  • A backup you have never restored is a hope, not a backup. CISA's guidance is to test the availability and integrity of backups regularly.

What is a NAS, and when does a homelab need one?

A NAS is a file server you reach over the network. It exports storage as shared folders (SMB for Windows, macOS and most phones, NFS for Linux and hypervisors) and sometimes as block devices (iSCSI) for virtual machines. NIST SP 800-209 covers network attached storage alongside block and file storage services, and its list of attack surfaces includes physical access, the storage operating system, management hosts, and management APIs and software. That is a useful way to think about a home box too: the disks, the operating system, the shares and the admin interface each need their own protection.

Three kinds of NAS show up in homelabs:

  • Turnkey NAS appliances. A small enclosure with two to eight drive bays, a low power CPU and a vendor operating system with a web interface and an app catalog. Easy to start, but you depend on the vendor for firmware and security updates, and the web interface becomes something you must patch.
  • A NAS focused operating system on your own hardware. Several open source storage distributions package ZFS, SMB, NFS and a web interface into an installer. You pick the hardware, the distribution handles most configuration.
  • A general Linux server you configure yourself. A Debian or Ubuntu machine with OpenZFS, Samba and the kernel NFS server. This guide uses this route because every step is visible, and the same commands work underneath the other two.

NAS vs external drive vs cloud storage

OptionGood forWeak spotsCounts toward 3-2-1?
Single external USB driveOne laptop's backup, an offline copy you unplugNo redundancy, easy to drop, USB bridges can hide sector size and SMART dataYes, as one copy on its own medium, especially when kept unplugged
Home NAS with redundancyShared family storage, VM and container volumes, a central backup target for other machinesSame building, same power, same admin credentials as the rest of the labYes, as one copy, but not as the only backup
Cloud object or backup storageThe off site copyUpload time for large data, monthly cost, account takeover risk, provider termsYes, as the off site copy
Second ZFS box at a friend's or relative's houseThe off site copy with zfs send replicationNeeds a VPN or SSH path and someone to power cycle itYes, as the off site copy

You probably need a NAS when two or more of these are true: several people or machines need the same files; your data is bigger than one drive; you run virtual machines or containers that need shared storage (the 3-node homelab Kubernetes cluster is a common example); or you want one place that backs up every laptop and phone in the house. If all you have is one laptop, an external drive plus a cloud backup is simpler and safer than a NAS you will not maintain.

How do RAID 1, 5, 6, 10 and ZFS mirrors and RAIDZ compare?

RAID (redundant array of independent disks) combines disks so that the loss of one or more does not lose data. The classic levels were defined for hardware controllers and are implemented on Linux by the kernel md driver. ZFS has its own equivalents built into the file system.

  • RAID 1 / ZFS mirror. Every disk holds a full copy. The zpoolconcepts man page says a mirror of N disks of size X "can hold X bytes and can withstand N-1 devices failing."
  • RAID 5 / RAIDZ1. Data plus one parity block per stripe. Survives one disk failure.
  • RAID 6 / RAIDZ2. Data plus two parity blocks. Survives two disk failures.
  • RAIDZ3. Three parity blocks. Survives three. There is no common classic RAID level equivalent.
  • RAID 10 / striped ZFS mirrors. Several mirrors with data spread across them. In ZFS this is simply a pool with more than one mirror vdev, for example zpool create mypool mirror sda sdb mirror sdc sdd, which is the exact example in zpoolconcepts. It survives one failure per mirror, but losing both disks of any one mirror loses the pool.
  • dRAID. A RAIDZ variant with distributed hot spares, meant for large disk counts. The man page notes it uses a fixed stripe width, so "with the default D=8 and 4 KiB disk sectors the minimum allocation size is 32 KiB." It is rarely the right choice for under a dozen disks.

The OpenZFS RAIDZ page gives the capacity rule: a RAIDZ group of N disks of size X with P parity disks "can hold approximately (N-P)*X bytes and can withstand P devices failing." It also says the minimum number of devices is one more than the parity level and the recommended width is between 3 and 9 disks.

Usable capacity, worked examples

All examples use 12 TB drives. Drive makers count a terabyte as 10^12 bytes, while most operating systems report in tebibytes (2^40 bytes), so one 12 TB drive shows up as about 10.9 TiB. Multiply any figure below by 0.909 to get what zpool list will roughly report before metadata and padding.

LayoutDisksRawUsable (approx.)SurvivesUsable share
Two-way mirror (RAID 1)224 TB12 TB1 disk50%
Two mirrors striped (RAID 10)448 TB24 TB1 per mirror50%
RAIDZ1 (RAID 5)448 TB36 TB1 disk75%
Three mirrors striped672 TB36 TB1 per mirror50%
RAIDZ2 (RAID 6)672 TB48 TB2 disks67%
RAIDZ2896 TB72 TB2 disks75%
RAIDZ3896 TB60 TB3 disks63%

Example 1, a six bay box. Six 12 TB disks as RAIDZ2 gives (6 minus 2) times 12 = 48 TB, about 43.6 TiB, and any two disks can fail. The same six disks as three mirrors give 36 TB, about 32.7 TiB. You trade 12 TB of space for faster random reads, faster resilvers and the ability to grow two disks at a time.

Example 2, why "approximately" matters. The OpenZFS RAIDZ page works through a three disk RAIDZ1 with ashift=12 (4 KiB sectors). With the default 128 KiB record size, each stripe holds 8 KiB of data and 4 KiB of parity, so storing 128 KiB writes 192 KiB, a 66% usable ratio, which matches (3 minus 1) divided by 3. With a 4 KiB record size, every block is one data sector plus one parity sector, so the usable ratio falls to 50%, "same as with double mirror." Small blocks on RAIDZ waste space. That is why virtual machine disks and databases with small blocks are usually better on mirrors.

Rebuild risk: what happens when a disk dies

When a disk fails, the array is degraded and must rebuild onto a replacement. During that window the remaining disks are read hard, and any further failure or unreadable sector is where data loss happens.

  • Classic RAID 5 rebuilds the whole disk. The md driver reconstructs every sector, used or not. The kernel md documentation also warns that if a RAID 5 or RAID 6 array is both dirty (after an unclean shutdown) and degraded, "it could have undetectable data corruption," because parity cannot be trusted and a block is missing.
  • ZFS resilvers only allocated data. The zpool-scrub man page explains that resilvering "only examines data that ZFS knows to be out of date," so a half empty pool rebuilds in roughly half the time of a full one. And because every block has a checksum, ZFS knows which blocks it could not reconstruct and can list the affected files with zpool status -v instead of silently returning bad data.
  • Unreadable sectors during a rebuild. Drive datasheets state a maximum unrecoverable read error rate, often written as one error per a number of bits read. Rebuilding a 4 x 12 TB RAIDZ1 reads the three surviving disks, 36 TB or 2.88 x 10^14 bits. If a datasheet's worst case is one error per 10^14 bits, the arithmetic says a full read is in the range where the specification no longer promises a clean pass. Real drives usually do better than their worst case, but this is the reason single parity is a poor fit for large disks. With RAIDZ2 a read error during a single disk rebuild can still be corrected from the second parity.
  • Rebuilds take time. Writing 12 TB at a sustained 200 MB/s takes about 16.7 hours before any other load. Wider and fuller pools take longer. During that time, a second failure on RAIDZ1 or on the wrong disk of a mirror pair loses data.
  • Drive managed SMR disks make rebuilds much slower. The OpenZFS hardware page says DM-SMR drives "can trigger severe write-amplification stalls during RAIDZ/mirror resilver, scrub, and zfs send/receive workloads."

Since OpenZFS 2.4, the RAIDZ page notes, a persistently slow disk in a RAIDZ group can be put in a "sit out" state where reads skip it and reconstruct its data from parity while writes still go to it. That helps when one ailing drive drags the whole group down, but it is not a substitute for replacing that drive.

Comparison table of layouts

LayoutMin disksFailures toleratedUsable share (6 disks)Random readResilverGrow byBest fit
Single disk10100%One diskNone possibleAdd vdevScratch data you can lose
Mirror (2-way)21 per mirror50%Scales with mirrorsFast, copies one diskTwo disks (one new mirror) or bigger disksVMs, containers, databases, small pools
Mirror (3-way)32 per mirror33%Scales with mirrorsFastThree disksSmall, critical data
RAIDZ13183%About one diskSlower, reads all disksOne disk at a time (RAIDZ expansion)Small disks, data that is backed up elsewhere
RAIDZ24267%About one diskSlowerOne disk at a timeMedia, photos, general file storage on large disks
RAIDZ35350%About one diskSlowerOne disk at a timeWide pools of very large disks
dRAIDMany1 to 3 plus sparesVariesLike RAIDZSequential, fastNot in placeLarge disk shelves, not typical homelabs
md RAID 5 / 6 (no ZFS)3 / 41 / 283% / 67%GoodWhole diskOne disk, with reshapeWhen you need ext4 or XFS on top

The "about one disk" random read figure for RAIDZ comes from the OpenZFS RAIDZ page, which says that with the default 128 KiB record size, "random-read IOPS then works out roughly the same as a single disk's, however wide the group," and that "mirrors remain the better choice when random-read IOPS is the binding constraint."

Decision table by use case

You mainly storeDisksSuggested layoutWhy
Family photos, documents, a few TB2Two-way mirrorSimple, fast, survives one disk, easy to grow with bigger disks
Media library, large files, 4 to 8 bays6 to 8RAIDZ2Good capacity, survives two failures during long rebuilds
VM disks and container volumes4 to 6Striped mirrorsSmall random I/O, fast resilver
Mixed: media plus VMs6 HDD plus 2 SSDRAIDZ2 pool for media, separate SSD mirror pool for VMsEach workload gets the layout that suits its block size
Backup target for other machines4 to 6RAIDZ2Mostly sequential writes; capacity matters
Off site backup box2 to 4Mirror or RAIDZ1This is a second copy; it can carry less redundancy than primary
Lab experimentsAnyWhatever you likeAs long as nothing irreplaceable lives there

Why does ZFS use copy-on-write and checksums, and what do scrubs catch?

Copy-on-write in plain terms

Traditional file systems overwrite blocks in place. If power drops halfway through an update, you can end up with half old and half new data, and a classic RAID 5 can end up with data and parity that disagree. That gap is the "write hole" the OpenZFS RAIDZ page refers to when it says RAIDZ "eliminates the RAID-5 'write hole' (in which data and parity become inconsistent after a power loss)."

ZFS never overwrites live data. A change is written to free space, then the pointers above it are updated, all the way up the tree, and the new tree becomes current in one atomic step. If power fails mid write, the old tree is still intact. The same property makes snapshots cheap: a snapshot simply keeps the old tree's blocks from being freed. The zfsconcepts man page describes snapshots as read only copies that "can be created extremely quickly, and initially consume no additional space within the pool."

The kernel md driver closes the write hole differently. Its documentation lists a write journal device for RAID 4, 5 and 6 "to log transactions and replay after unclean shutdown," and a Partial Parity Log for RAID 5 "to close the write hole and eliminate resync." These work, but they are extra configuration you have to choose.

End to end checksums

The OpenZFS checksums page calls end to end checksums "a key feature of ZFS." Each block's checksum is computed when the block is written and stored in its parent block pointer, not next to the data. That matters because a disk that returns the wrong sector, or a controller that writes to the wrong place, will produce data that does not match the checksum held elsewhere.

The page lists what that buys you: corruption is detected on read; corrupt blocks "are automatically repaired if possible, by using the RAID protection in suitably configured pools, or redundant copies"; scrubs can "detect and repair latent media degradation (bit rot)"; and checksums on zfs send and zfs receive streams make sure replicated data is not corrupted in transit.

The default checksum=on means fletcher4 for normal datasets and sha256 for deduplicated ones. Changing the algorithm only affects blocks written after the change. The page also lists off with the plain note "Do not use."

What a scrub actually does

The zpool-scrub man page says a normal scrub "examines all data in the specified pools and verifies each block's checksum," and that for mirror, RAIDZ and dRAID vdevs, "ZFS automatically repairs any damage discovered during the scrub." Scrubs are sorted into large sequential ranges first, so they read disks efficiently, and only one scrub or resilver runs at a time.

A scrub catches:

  • Sectors that have silently gone bad since they were written.
  • Blocks a disk or cable wrote incorrectly, or wrote to the wrong place.
  • A disk that is starting to fail, visible as climbing READ or CKSUM counts in zpool status.
  • Problems on data you rarely read, such as old photo archives, long before a rebuild depends on it.

A scrub does not catch:

  • Bit flips in RAM before the checksum was calculated. The OpenZFS hardware page is direct about this: if a bit flip "occurs before ZFS' checksum calculation, ZFS will not realize that the data is corrupt."
  • Files that were deleted, overwritten or encrypted by a user or by malware. To ZFS those are valid new writes with valid checksums.
  • Problems on a single disk pool with no redundancy. ZFS can detect the error but has no second copy to repair from, unless you set copies=2 on a dataset.

The md driver has a comparable check action, written to the array's sync_action file, which "reads all blocks and checks them." Because md has no per block checksum, it can tell you that mirror halves or parity disagree (reported in mismatch_cnt) but not which copy is the correct one.

OpenZFS ships systemd timers to run scrubs on a schedule: zfs-scrub-weekly@.timer and zfs-scrub-monthly@.timer are in the project's etc/systemd/system directory. Monthly is a common choice for home pools of large disks.

How do snapshots, send/receive replication and the 3-2-1 rule fit together?

These are three layers, and each one covers a failure the others miss.

LayerProtects againstDoes not protect againstRestore time
Redundancy (mirror, RAIDZ)A disk dyingDeletion, overwrite, ransomware, theft, fire, a pool level bugNone, the pool stays online
Snapshots in the same poolAccidental deletion or overwrite, a bad upgrade inside a datasetLosing the pool, an admin or attacker destroying snapshots, fireSeconds
Replication to another machineLosing the primary pool or the whole NASFire or theft if the second machine is in the same room; credential compromise if it trusts the primaryMinutes to hours
Offline or off site copyFire, theft, ransomware that reaches every online systemData written after the last copyHours to days

Snapshots

A snapshot is a read only, point in time view of a dataset. You can browse it under the hidden .zfs/snapshot directory at the dataset root, as zfsconcepts describes, which makes single file restores easy for anyone with read access. Snapshots initially consume no space and grow only as live data diverges.

NIST SP 800-209 gives two snapshot rules that translate well to a homelab. DP-SS-R10 says snapshot schedules should meet your recovery point objective and retention needs; its example is that if hourly copies are needed for 48 hours, keep enough hourly snapshots. DP-SS-R11 says "obsolete snapshots and clones should be removed to reduce the attack surface." The same document's section on snapshots warns that a snapshot stores only changed data relative to the source, which "often means that if the source data is unavailable, the snapshots will not be usable as well." That one sentence is the reason snapshots are not backups.

A practical home schedule: every 15 minutes kept for a day on datasets that change often, hourly for two days, daily for a month, monthly for a year. Several open source snapshot management tools automate rotation; any of them works if you can read and test its configuration.

Send and receive

zfs send turns a snapshot, or the difference between two snapshots, into a stream. zfs receive turns the stream back into a dataset on another pool, often on another machine over SSH. The options that matter most:

  • -i sends the changes between two snapshots (an incremental). -I sends all intermediate snapshots too, so the destination keeps the same history.
  • -R (replicate) sends a dataset and all its children "up to the named snapshot," and on receive "all properties, snapshots, descendent file systems, and clones are preserved," per the zfs-send man page.
  • -w (raw) sends encrypted datasets "exactly as it exists on disk," so the backup "may then be received on an untrusted machine since that machine will not have the encryption keys." This is ideal for an off site box at someone else's house.
  • On the receiving side, -s saves partial state if the stream is interrupted, so a later send can resume, and -u leaves the received file system unmounted.
  • -F on receive forces a rollback of the destination and, with replication streams, can destroy snapshots and file systems on the destination that no longer exist on the source. It is useful, and it is also how a compromised or mistaken source can wipe history on the backup. Use it deliberately.

The 3-2-1 rule

The US-CERT paper Data Backup Options (Ruggiero and Heckathorn, 2012), still hosted by CISA, states the rule plainly: keep 3 copies of any important file, "1 primary and 2 backups"; keep them on 2 different media types; and store 1 copy off site. For a ZFS homelab, a common mapping is:

  1. Primary: the NAS pool, with snapshots.
  2. Second copy: a separate ZFS machine or a large external disk pool that receives replication.
  3. Off site: a second ZFS box elsewhere receiving raw sends over a VPN, or a cloud backup of the most important datasets, or rotated external disks kept at another address.

"Two media types" is harder to honor literally at home. The intent is that one failure mode (a bad drive batch, a single cloud account) cannot take out every copy. A second pool on drives from a different batch, plus a cloud copy, satisfies that intent.

How do you choose NAS hardware?

ECC memory

The OpenZFS hardware page says "No technique used in ZFS (or any other filesystem) is capable of protecting against bit flips. Consequently, ECC Memory is highly recommended." It explains the cases: a flip before checksum calculation means ZFS stores bad data with a good checksum; a flip after the checksum but before write out will be detected later but might not be correctable.

In practice, ECC means a CPU, motherboard and memory that all support it. Many small server and workstation platforms do. A NAS without ECC still benefits from ZFS checksums on the disk side; it just cannot detect corruption that happens in memory. The more important your data, the more ECC is worth.

CMR vs SMR drives

The hardware page says drive managed shingled magnetic recording (DM-SMR) drives "are therefore not recommended for ZFS pools" and that conventional magnetic recording (CMR) drives "should be preferred for any redundant pool." It adds that the recording technology "is frequently not stated in the model number," so confirm the exact model with the manufacturer and with independent sources. Look for the words CMR, PMR, non-shingled or non-SMR on the datasheet for the full model number, not the product family.

Error recovery control

Desktop drives can spend minutes retrying a bad sector, which stalls the whole pool. The hardware page explains that enterprise and some consumer drives support a time limit on error recovery (sold under names such as TLER, ERC and CCTL), that drives with it "typically default to 7 seconds," and that ZFS does not change this setting itself. The smartctl man page shows how to read and set it with -l scterc, in tenths of a second, and notes that "For RAID configurations, this is typically set to 70,70 deciseconds." The OpenZFS page goes further and suggests a much lower value such as 0.1 seconds, while the smartctl page warns that values below 65 "are probably not supported." Most home builders use 70,70 and treat the lower value as an expert tweak.

# Read the current error recovery setting (ATA drives only)
sudo smartctl -l scterc /dev/disk/by-id/ata-EXAMPLE_SERIAL

# Set read and write recovery limits to 7.0 seconds (not persistent on many drives)
sudo smartctl -l scterc,70,70 /dev/disk/by-id/ata-EXAMPLE_SERIAL

On many drives the setting resets at power cycle, so run it from a boot time unit.

HBA, not a RAID controller

The hardware page says "Hardware RAID controllers should not be used with ZFS." A RAID controller hides individual disks, may pass sector sizes incorrectly, and takes away ZFS's ability to repair a bad block from a good copy. It also warns against the workaround of single disk RAID 0 volumes and concludes "It is best to use a HBA instead of a RAID controller, for both performance and reliability."

A host bus adapter (HBA) presents each disk directly to the operating system. Many SAS controllers can run either RAID firmware or plain pass through firmware, which the homelab community usually calls IT (initiator target) mode. If you buy a used controller, check which firmware it runs. Reflashing controller firmware is model specific, can render the card unusable if done wrong, and should follow the card maker's own instructions. Motherboard SATA ports in AHCI mode are also fine for ZFS.

USB enclosures are a weaker choice for a permanent pool. The hardware page notes that drives "are known to properly identify themselves unless behind a USB to SATA controller," which can lead to the wrong sector size. USB disks are fine for offline backup pools you import, update and export.

Sector size and ashift

ZFS writes in units of 2 to the power ashift. The tuning page says ashift is set when a top level vdev is created "and it is immutable." Modern hard drives use 4 KiB physical sectors (ashift=12). The zpoolprops page allows values from 9 to 16 and says the default of 0 auto detects. Setting ashift=12 explicitly avoids a pool stuck at 512 byte alignment because one drive or bridge misreported. The tuning page says flash media will be either 12 or 13.

Power draw and cost

A NAS runs all day, so watts matter more than peak speed. The arithmetic: a box that averages 60 W uses 60 x 24 x 365 = 525.6 kWh a year. At an illustrative tariff of 0.15 per kWh that is about 79 a year in your currency, and at 0.30 it is about 158. Each 3.5 inch hard drive adds several watts at idle (check the datasheet for the model), so six drives can draw more than the board. Ways to cut it: fewer, larger drives; a low power CPU; SSDs for the always busy VM pool; and spinning down only disks that are truly idle, since frequent spin ups have their own wear cost.

Add an uninterruptible power supply that signals the NAS over USB so it shuts down cleanly. Copy-on-write keeps ZFS consistent after a power cut, but a clean shutdown is still kinder to the drives.

How do you build a ZFS pool on Linux step by step?

This walkthrough uses Debian or Ubuntu, six disks in RAIDZ2 and a pool called tank. Read every warning. The commands that create a pool or wipe signatures destroy whatever is on the named disks.

Step 1: Install OpenZFS

On Ubuntu, the OpenZFS getting started page says to install zfsutils-linux:

sudo apt update
sudo apt install zfsutils-linux

On Debian, ZFS lives in the contrib component. The OpenZFS Debian page uses the backports repository and installs kernel headers, then the DKMS module:

sudo apt update
sudo apt install linux-headers-$(dpkg --print-architecture)
sudo apt install zfs-dkms zfsutils-linux

Check what you installed:

zfs version

As of this writing the OpenZFS project's latest releases, published on 21 August 2026, are 2.4.4, 2.3.9 and 2.2.11. Your distribution may ship an older supported branch.

Step 2: Identify the disks by stable IDs

Names like /dev/sda can change between boots. Use /dev/disk/by-id/, which includes the model and serial number.

lsblk -o NAME,SIZE,MODEL,SERIAL,TRAN,MOUNTPOINTS
ls -l /dev/disk/by-id/ | grep -v part

Write down each serial number and match it to the label on the physical drive, or to the bay it sits in. You will need this mapping when a drive fails and you have to pull the right one.

Step 3: Check drive health before you trust it

# Health summary, identity and attributes
sudo smartctl -a /dev/disk/by-id/ata-EXAMPLE_SERIAL

# Start an extended self test (runs in the background, tens of minutes to hours)
sudo smartctl -t long /dev/disk/by-id/ata-EXAMPLE_SERIAL

# Later, read the self test log
sudo smartctl -l selftest /dev/disk/by-id/ata-EXAMPLE_SERIAL

The smartctl man page describes the long test as "a longer and more thorough version of the Short Self Test" that can run during normal operation. Reject any new drive that reports reallocated or pending sectors, and confirm the model is CMR before it goes in the pool.

Step 4: Confirm the target disks are empty and unused

Warning: the next steps destroy data. Before running Step 5 or Step 6, confirm that each path refers to the disk you intend, that it is not mounted, not part of another pool or RAID array, and not your boot disk. If you are unsure about any disk, stop.

Run these checks for every disk you plan to use:

DISK=/dev/disk/by-id/ata-EXAMPLE_SERIAL

# 1. Resolve the stable ID to the kernel name and confirm model, size and serial
readlink -f "$DISK"
lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,MOUNTPOINTS "$DISK"

# 2. Confirm nothing on it is mounted
findmnt -S "$(readlink -f "$DISK")" || echo "not mounted"

# 3. Confirm it is not in an existing pool or md array
sudo zpool status 2>/dev/null | grep -F "$(basename "$DISK")" || echo "not in a pool"
grep -F "$(basename "$(readlink -f "$DISK")")" /proc/mdstat || echo "not in md"

# 4. List existing signatures WITHOUT removing them (-n is a dry run)
sudo wipefs -n "$DISK"

Only if every check is clean, and the disk previously held data you no longer need, remove old signatures:

Warning: wipefs -a erases partition table and file system signatures on the named device. Re-run the four checks above immediately before this command.

sudo wipefs -a "$DISK"

If you are retiring old drives rather than reusing them, a signature wipe is not a secure erase. Our posts on NVMe and ATA sanitize commands and deep cleaning and secure delete on Linux cover that properly.

Step 5: Dry run the pool layout

zpool create -n "Displays the configuration that would be used without actually creating the pool," per the zpool-create man page. Use it every time.

sudo zpool create -n -o ashift=12 tank raidz2 \
  /dev/disk/by-id/ata-DISK1_SERIAL \
  /dev/disk/by-id/ata-DISK2_SERIAL \
  /dev/disk/by-id/ata-DISK3_SERIAL \
  /dev/disk/by-id/ata-DISK4_SERIAL \
  /dev/disk/by-id/ata-DISK5_SERIAL \
  /dev/disk/by-id/ata-DISK6_SERIAL

Read the output. It should show one raidz2 vdev with exactly six children, each the by-id path you expected.

Step 6: Create the pool

Warning: this formats all six disks. Confirm the dry run output, and confirm none of these paths is your boot disk, before you remove -n. Do not add -f unless you understand exactly why ZFS refused; the man page says -f "Forces use of vdevs, even if they appear in use."

sudo zpool create \
  -o ashift=12 \
  -O compression=on \
  -O atime=off \
  -O xattr=sa \
  -O mountpoint=/tank \
  tank raidz2 \
  /dev/disk/by-id/ata-DISK1_SERIAL \
  /dev/disk/by-id/ata-DISK2_SERIAL \
  /dev/disk/by-id/ata-DISK3_SERIAL \
  /dev/disk/by-id/ata-DISK4_SERIAL \
  /dev/disk/by-id/ata-DISK5_SERIAL \
  /dev/disk/by-id/ata-DISK6_SERIAL

sudo zpool status tank
sudo zfs list

What the options do, from zfsprops: compression=on selects the current default algorithm, which is lz4 when the lz4_compress feature is enabled; atime=off stops access time updates, which "avoids producing write traffic when reading files"; xattr=sa stores extended attributes as system attributes. Lowercase -o sets pool properties, uppercase -O sets file system properties on the root dataset.

For a two disk mirror the shape is the same with mirror DISK1 DISK2. For striped mirrors, repeat mirror A B mirror C D.

Step 7: Create datasets, with encryption where it matters

Datasets are cheap. Make one per purpose so each can have its own snapshots, quotas and share settings.

sudo zfs create tank/media
sudo zfs create tank/backups
sudo zfs create -o recordsize=1M tank/media/video

# An encrypted dataset; you will be asked for a passphrase
sudo zfs create -o encryption=on -o keyformat=passphrase tank/private

The zfsprops page says encryption=on currently selects aes-256-gcm and that encryption must be chosen when the dataset is created. Encrypted datasets can later be replicated with zfs send -w so the backup machine never holds the key.

Step 8: Schedule scrubs and alerts

# Run a first scrub now and watch it
sudo zpool scrub tank
sudo zpool status tank

# Enable the monthly scrub timer shipped by OpenZFS
sudo systemctl enable --now zfs-scrub-monthly@tank.timer

# Daily health check you can wire into mail or a notifier
sudo zpool status -x

zpool status -x displays only pools "exhibiting errors or are otherwise unavailable," so a healthy system prints a one line all clear. The ZFS Event Daemon (zfs-zed.service in the OpenZFS systemd units) can send notifications on device faults; configure its mail settings so a degraded pool does not sit unnoticed for months.

Step 9: Take and protect snapshots

# Recursive snapshot of every dataset in the pool
sudo zfs snapshot -r tank@2026-10-23

# See them
zfs list -t snapshot -o name,used,creation

# Put a hold on a snapshot you want to keep
sudo zfs hold -r keep tank@2026-10-23
zfs holds -r tank@2026-10-23

The zfs-hold man page says that if a hold exists, "attempts to destroy that snapshot by using the zfs destroy command return EBUSY." A hold protects against mistakes and careless scripts. It does not stop someone with root on the NAS, who can release the hold first. That is why the next step matters.

Step 10: Replicate to a second machine with its own credentials

The safest pattern for home use is a pull: the backup machine connects to the NAS and pulls snapshots, so the NAS never holds credentials that can write to, or delete from, the backup.

On the backup machine, give a dedicated unprivileged user the minimum ZFS permissions on its target dataset. The zfs-allow man page lists a receive:append permission, a "limited receive ability (can not do receive -F)," which requires create and mount as well:

# On the backup machine
sudo zfs create backup/nas
sudo zfs allow -u zfsrecv create,mount,receive:append backup/nas

On the NAS, allow a dedicated user to send but not destroy. OpenZFS 2.4 adds send:raw, which only permits raw streams so encrypted datasets cannot be sent in decrypted form:

# On the NAS (OpenZFS 2.4 or later for send:raw; use send on 2.3)
sudo zfs allow -u zfssend send:raw,hold tank

Then, run from the backup machine (the first time is a full send, after that incrementals):

# Initial full replication of the encrypted dataset
ssh zfssend@nas zfs send -w tank/private@2026-10-23 \
  | zfs receive -u -s backup/nas/private

# Later: send everything between the last common snapshot and the newest one
ssh zfssend@nas zfs send -w -I tank/private@2026-10-23 tank/private@2026-10-30 \
  | zfs receive -u -s backup/nas/private

Because the user on the backup side cannot use receive -F, a source that has had its snapshots destroyed cannot propagate that destruction by forcing a rollback on the backup. Rotate snapshots on the backup machine with its own schedule and its own retention, rather than mirroring deletions from the NAS.

Step 11: Replace a failed disk

sudo zpool status -v tank      # find the FAULTED or UNAVAIL device and its by-id name
# Physically swap the drive, matching the serial number you recorded in Step 2

Warning: run the Step 4 checks on the new disk first, and make sure the old path in the command is the failed disk, not a healthy one.

sudo zpool replace tank /dev/disk/by-id/ata-FAILED_SERIAL /dev/disk/by-id/ata-NEW_SERIAL
sudo zpool status tank          # watch the resilver

Step 12: Grow the pool

  • Mirrors: add another mirror vdev, or replace each disk of a mirror with a larger one and let it resilver.
  • RAIDZ: since OpenZFS 2.3.0 (released 14 January 2025), you can widen a RAIDZ vdev one disk at a time with zpool attach tank raidz2-0 NEW_DISK. The zpool-attach man page says redundancy is maintained during the expansion, and the RAIDZ page notes that blocks written before the expansion "keep their original data-to-parity ratio," so only new writes get the wider ratio.

How should you share data safely?

SMB: SMB3 only, signing or encryption, LAN only

Samba is the standard SMB server on Linux. A cautious smb.conf for a home NAS:

[global]
   server role = standalone server
   server min protocol = SMB3_00
   server signing = mandatory
   server smb encrypt = desired
   interfaces = lo 192.168.10.0/24
   bind interfaces only = yes
   hosts allow = 127.0.0.1 192.168.10.0/24
   hosts deny = 0.0.0.0/0
   map to guest = never

[photos]
   path = /tank/photos
   valid users = @family
   read only = no
   server smb encrypt = required

What the man page says about each choice:

  • server min protocol defaults to SMB2_02. Setting SMB3_00 refuses SMB1 and SMB2 clients; the page lists SMB3_00 as the Windows 8 SMB3 version and SMB3_11 as the Windows 10 version.
  • server signing defaults to default, which means signing is required only on an Active Directory domain controller and is otherwise off. For SMB2 and later, "by design, signing cannot be disabled," and mandatory "will still require SMB2 clients to use signing."
  • server smb encrypt accepts off, if_required, desired and required. With SMB2 and newer it controls SMB3 transport encryption, "available in Windows 8 and newer." Setting it to required on a share denies connections that cannot encrypt.
  • hosts allow with no value permits all hosts. The man page also notes that access "still requires suitable user-level passwords," so this is an extra filter, not authentication.

Run testparm after editing to catch typos. Our deeper post on SMB2 and SMB3 dialects, signing and encryption covers what each dialect negotiates.

NFS: NFSv4, restricted exports, Kerberos if you can

NFS is common between Linux hosts and hypervisors. The exports man page is blunt about the default security flavor: sec=sys is "the default, no cryptographic security." It lists krb5 (authentication only), krb5i (integrity) and krb5p (privacy, meaning encryption).

# /etc/exports: one host or subnet per line, never a wildcard
/tank/k8s    192.168.10.21(rw,sync,no_subtree_check,root_squash,sec=krb5p)
/tank/media  192.168.10.0/24(ro,sync,no_subtree_check,root_squash)

root_squash maps requests from user ID 0 to the anonymous user. The man page warns that it "does not apply to any other uids or gids that might be equally sensitive." Without Kerberos, any machine on the allowed subnet that can claim a user ID gets that user's access, so keep NFS exports to the smallest set of hosts and to their own VLAN. See our NFSv4 security, Kerberos and exports post for the full setup.

No WAN exposure, VPN only

Do not forward SMB, NFS or the NAS web interface through your router. File sharing protocols and storage admin pages are high value targets and were never designed to face the internet. If you need files away from home, connect to your home network over a VPN first, then use the shares as if you were home. If you also run apps such as photo or file sync services from the NAS, our guide on self-hosting photos, files and calendar and the companion is it safe to self-host apps on the internet explain how to publish an app without publishing the storage behind it.

NIST SP 800-209 recommendation IS-SS-R6 applies to recovery storage in particular: disable all unnecessary services and protocols, and where a command line or API is enough for management, "disable any interactive web interfaces." On a home backup box that means SSH only, no SMB, no NFS, no web console.

What about ransomware?

Ransomware that reaches a machine with a mapped NAS share can encrypt everything that machine can write to. To ZFS, those encrypted files are legitimate writes with valid checksums. Redundancy will faithfully store the damage on every disk.

CISA's #StopRansomware Guide (September 2023 update of the 2020 guide, co-authored with MS-ISAC, NSA and FBI) puts it first in its preparation list: "Maintain offline, encrypted backups of critical data, and regularly test the availability and integrity of backups in a disaster recovery scenario." It explains why offline matters: many ransomware variants "attempt to find and subsequently delete or encrypt accessible backups." For recovery it says to restore "from offline, encrypted backups based on a prioritization of critical services," and to check for dropper malware "before rebuilding from backups."

Are ZFS snapshots immutable?

They are read only, which protects them from a client that only has share access. A Windows machine with an SMB mapped drive cannot modify a snapshot. That alone defeats a lot of commodity ransomware. But snapshots are not immutable to anyone with administrative access to the NAS: root can release holds and destroy snapshots, or destroy the pool. Treat NAS snapshots as protection against client side encryption and mistakes, not against someone who owns the NAS.

Building something closer to immutable at home

NIST SP 800-209 section 4.7 describes isolation for "cyber-attack recovery copies." Scaled down to a homelab, its recommendations become:

NIST SP 800-209 recommendationHomelab version
IS-SS-R1: recovery copies on separate storageA second ZFS machine, not another dataset in the same pool
IS-SS-R2: separate management systems, not reachable with regular credentialsDifferent admin passwords and SSH keys on the backup box; never log in to it from the NAS
IS-SS-R3: access limited to a very small group with separate credentialsOnly you, with a key that lives nowhere else
IS-SS-R4: off site storageA box or rotated disks at another address
IS-SS-R5: independent full baseline copyKeep a full replicated copy, not just snapshots that depend on the primary
IS-SS-R7: recovery copies not mounted or exported to hostsThe backup pool is never shared over SMB or NFS; restore to a staging dataset first
IS-SS-R8: consider an air gapAn external disk pool that is imported, updated and exported, then unplugged
IS-SS-R10: consider immutable storageObject storage with retention locks for the off site copy, if your provider supports it

CISA adds a caution on that last row: some cloud vendors offer immutable storage, but "Use immutable storage with caution as it does not meet compliance criteria for certain regulations and misconfiguration can impose significant cost."

An offline USB pool in practice:

# Plug in the backup disk, import the pool, receive, then detach it
sudo zpool import offline1
zfs send -w -I tank/private@2026-10-01 tank/private@2026-10-23 \
  | sudo zfs receive -u offline1/private
sudo zpool scrub -w offline1     # -w waits until the scrub finishes
sudo zpool export offline1
# Now unplug it and store it away from the NAS

Restore tests

A restore test proves three things: the copy exists, it is readable, and you remember how to use it. Do one every quarter, and after any change to your backup scripts.

# On the backup machine: clone a replicated snapshot into a scratch dataset
sudo zfs load-key backup/nas/private      # raw sends keep the source passphrase
sudo zfs clone backup/nas/private@2026-10-23 backup/restoretest
ls /backup/restoretest

# Compare a sample of files against the source
sha256sum /backup/restoretest/documents/taxes-2025.pdf
ssh nas sha256sum /tank/private/documents/taxes-2025.pdf

Warning: the next command destroys the scratch clone. Check the name twice; zfs destroy on the wrong dataset, or with -r on a parent, removes real data.

sudo zfs destroy backup/restoretest

Time the test. If restoring your photo library takes nine hours, you want to know that before you need it.

Dated milestones worth knowing

DateEventSource
2012US-CERT paper Data Backup Options sets out the 3-2-1 ruleCISA hosted PDF
September 2020CISA and MS-ISAC publish the first Ransomware GuideCISA #StopRansomware Guide, "What's New"
26 October 2020NIST SP 800-209, Security Guidelines for Storage Infrastructure, published finalNIST CSRC
September 2023#StopRansomware Guide update adds FBI and NSA as co-authors and cloud backup guidanceCISA
14 January 2025OpenZFS 2.3.0 released with RAIDZ expansion, fast dedup, Direct IO and JSON outputOpenZFS GitHub release
18 December 2025OpenZFS 2.4.0 releasedOpenZFS GitHub release
21 August 2026OpenZFS 2.4.4, 2.3.9 and 2.2.11 releasedOpenZFS GitHub releases

Common mistakes

  • Calling RAID a backup. Redundancy copies your mistakes and your ransomware to every disk instantly.
  • Building with /dev/sdX names. They change. A pool built on by-id paths survives reboots and controller changes, and the serial in the name tells you which drive to pull.
  • Buying drive managed SMR disks for a redundant pool. The OpenZFS hardware page recommends against it, and resilvers are where you feel it.
  • Putting ZFS on top of a hardware RAID volume. ZFS can detect corruption but cannot fix it, and the controller's own write cache adds a failure mode.
  • Choosing RAIDZ1 for large disks with no backup. A long rebuild with one parity disk leaves no margin for a second problem.
  • Never scrubbing. Silent corruption on rarely read files waits until a rebuild needs those blocks.
  • Letting the NAS push to the backup with full rights. A compromised NAS can then destroy the backup. Pull from the backup side with limited zfs allow permissions.
  • Using zfs receive -F without thinking. It can roll back and delete history on the destination.
  • Forwarding SMB, NFS or the admin page through the router. Use a VPN.
  • Never testing a restore. Until you have restored a file from each copy, you do not know the copy works.
  • Running wipefs -a, zpool create or zpool replace without re-checking the device. One wrong letter erases the wrong disk.

FAQ

Is RAID a backup?

No. RAID and ZFS redundancy keep data available when a disk fails. A backup is a separate copy on separate hardware, ideally with one copy off site and one offline, as in the 3-2-1 rule and CISA's ransomware guidance.

Is RAIDZ1 safe for a home NAS?

It survives one disk failure. With large modern disks, rebuilds take many hours and read every surviving disk, so a second problem during that window can lose data. RAIDZ1 is reasonable for small disks or for data that is fully backed up elsewhere. For a primary pool of large disks, RAIDZ2 or mirrors are safer.

Should I use ZFS mirrors or RAIDZ2?

Mirrors give faster random reads, quicker resilvers and easy growth two disks at a time, at 50% usable space. RAIDZ2 gives more usable space (67% with six disks) and survives any two disk failures, with random read performance closer to a single disk. Use mirrors for VMs and databases, RAIDZ2 for bulk files.

Do I need ECC memory for ZFS?

The OpenZFS hardware page says ECC is highly recommended, because no file system can protect against bit flips in RAM. ZFS without ECC still protects against disk side corruption. If your platform supports ECC at a modest cost, use it.

How often should I scrub a ZFS pool?

Monthly is a common choice for home pools of large hard drives, and OpenZFS ships zfs-scrub-monthly@.timer and zfs-scrub-weekly@.timer to schedule it. Scrub more often if the data is critical or the drives are old, and always check zpool status after each run.

Can I add a disk to an existing RAIDZ vdev?

Yes, since OpenZFS 2.3.0. Use zpool attach with the RAIDZ vdev name, such as raidz2-0. Parity level does not change, and existing data keeps its old data to parity ratio until it is rewritten.

Are ZFS snapshots protected from ransomware?

They are read only, so a client that only has access to a share cannot encrypt them. Anyone with root on the NAS can destroy them. Combine snapshots with a pulled replica on a separate machine and an offline copy.

Should I expose my NAS to the internet?

No. Keep SMB, NFS and the admin interface on your LAN, and reach them remotely through a VPN. If you need to share files publicly, publish a separate app with its own authentication rather than the storage itself.

Where Safeguard fits

Safeguard does not manage storage, configure ZFS, scan NAS firmware or appliances, detect ransomware or protect endpoints. The fit is with the software that a homelab NAS ends up running. Most home NAS builds grow a stack of open source containers on top of the pool: photo libraries, file sync servers, media servers, backup tools, reverse proxies and dashboards. Those images and the repositories you build them from carry open source dependencies with their own vulnerabilities. Safeguard can scan a source tree with safeguard scan --dir ., a container image with --image, or an existing SBOM with --sbom, and write results as JSON under ./output, so you can see which of your self hosted services carry a known vulnerable component and in which version.

A NAS is mostly disks and a file system, but the services that make it useful are open source software that gets rebuilt and redeployed every time you update a container. The fit here is indirect: the steps below cover the images and repositories you build and run on the NAS, not the drives, the controller firmware or a vendor appliance's operating system.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The demos below show Safeguard working on ordinary software projects, not on disks or file systems. They apply to the compose files, Dockerfiles and small repositories that define the services running on a homelab NAS.

The first demo is a real Safeguard CLI session. After install, safeguard opens the interactive terminal, you ask it to fix the lodash CVE in a repository, and it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. It ends with /permissions, /model and /scan. The same ask, approve and test loop fits a repository holding the custom web app or sync helper you run on your NAS.

Click through it at your own pace, or open it full screen.

Homelab services often run on a box that never leaves the house network. The local runner demo shows how to set up the runner on your own machine, approve it with its device code, and then scan from the terminal. A runner on the NAS host, or on a lab machine beside it, can scan the images and repositories that live there.

Click through it at your own pace, or open it full screen.

If you use Claude, the third demo shows how to connect Claude to the Safeguard MCP server with OAuth and choose which tools Claude can use. You can then ask about known vulnerabilities in the projects behind your self hosted services, using only the tools you allowed.

Click through it at your own pace, or open it full screen.

To try it on your own repositories, download Safeguard and follow the CLI documentation.

Quick check

Your six disk RAIDZ2 pool shows zero errors after every monthly scrub. A laptop with a mapped share gets ransomware and encrypts the share. Does the scrub help?

No. The encrypted files are valid new writes with valid checksums, so ZFS stores them correctly on every disk. What helps is a snapshot taken before the encryption, which the laptop could not modify, plus a pulled replica and an offline copy in case the NAS itself was reached.

You want to back up an encrypted dataset to a friend's house without giving their machine your key. Which send option do you use?

zfs send -w (raw). The zfs-send man page says raw streams send encrypted data exactly as it exists on disk, so the receiving machine stores it without ever holding the encryption key. You load the key only when you restore.

Sources

Last reviewed: 23 October 2026. OpenZFS features, defaults and man pages change between releases; check the documentation for the version your distribution ships before you run any command that creates, replaces or destroys storage.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.