# ZFS Metadata Eraser `erase-zfs-metadata.sh` permanently overwrites disk metadata that can identify a device as a ZFS vdev. It is intended for decommissioning or repurposing a device after it has been cleanly removed from its pool. ## What It Erases The script performs 10 overwrite passes over the first 4 MiB and the last 4 MiB of the target block device. It uses zeroes by default and can use random data when requested. These regions include: - MBR data and GPT primary partition table at the beginning of a disk. - GPT backup partition table at the end of a disk. - The four conventional ZFS vdev-label regions, including their redundant copies at both ends of the device. It does not overwrite the entire device. Data outside those metadata regions may remain recoverable. ## Requirements - Linux with Bash. - Root privileges. - `blockdev`, `dd`, `findmnt`, `lsblk`, and the ZFS `zpool` command. - A target device of at least 8 MiB that is not mounted and is not part of an imported ZFS pool. ## Use First, verify the target device carefully: ```bash lsblk --output NAME,SIZE,TYPE,MOUNTPOINTS zpool status -P ``` Then make the script executable and run it with the full block-device path: ```bash chmod +x erase-zfs-metadata.sh sudo ./erase-zfs-metadata.sh /dev/sdX ``` Use `--source random` to overwrite with data from `/dev/urandom` instead of the default zeroes: ```bash sudo ./erase-zfs-metadata.sh --source random /dev/sdX ``` The only accepted source values are `zeroes` and `random`. Random overwrites are typically slower and do not erase additional parts of the device; both modes overwrite the same first and last 4 MiB regions. Replace `/dev/sdX` with the actual device, such as `/dev/sdb`, `/dev/nvme0n1`, or a device-mapper path. Do not use the disk containing the running system. The script displays target details and requires this exact confirmation before it writes anything: ```text ERASE /dev/sdX ``` ## Safety Behavior Before overwriting, the script refuses to run when: - The supplied path is not a block device. - The device itself is mounted. - A child partition of the device is mounted. - `zpool status -P` shows the device in an imported pool. - The device is smaller than 8 MiB. These checks reduce common mistakes but are not a substitute for verifying the device identity yourself. The operation is destructive and cannot be undone. ## Prepare a ZFS Device For a device that belongs to a pool, first use the appropriate ZFS procedure, such as replacing or detaching the vdev, then export the pool if necessary. Confirm the target no longer appears in `zpool status -P` before running the eraser. Do not use this utility to remove a live vdev from an active pool. ## Verify After completion, inspect the device for residual filesystem or partition signatures: ```bash sudo wipefs --all --no-act /dev/sdX sudo zdb -l /dev/sdX ``` `wipefs --no-act` reports signatures without modifying the device. `zdb -l` should not find a readable ZFS label after a successful run. ## Recovery Assessment `verify-zpool-recovery.sh` checks whether ZFS can find and rewind an exported or faulted pool. It cannot restore labels that have been completely overwritten by the eraser, so recovery after a successful erase is unlikely. Use it before erasing a device, or when ZFS still detects at least part of the pool metadata. List pools ZFS can discover without modifying anything: ```bash sudo ./verify-zpool-recovery.sh ``` Check whether a specific pool can be recovered with a transaction rewind. This uses `zpool import -nF`, which is a dry run: ```bash sudo ./verify-zpool-recovery.sh tank ``` If vdevs must be found in a non-default directory, supply it explicitly: ```bash sudo ./verify-zpool-recovery.sh --directory /dev/disk/by-id tank ``` After reviewing the dry-run output, attempt the import with rewind recovery: ```bash sudo ./verify-zpool-recovery.sh --apply tank ``` `--apply` runs `zpool import -N -F`: `-F` may discard the most recent transaction groups, and `-N` imports the pool without mounting datasets. The script requires the exact confirmation `RECOVER tank` before issuing that command. Inspect the result with `zpool status tank` before mounting datasets or performing any further changes.