Replacing a failed disk in the ZFS root | INTROSERV
EUR
european

EUR

usa

USD

English En
Ex. VAT Ex. VAT 0%

Replacing a failed disk in the ZFS root

This guide explains how to replace a failed disk in a ZFS mirror pool on Linux. The procedure covers taking the disk offline, copying the partition table to the replacement disk, re-adding the disk to the pool, and installing the bootloader after resilvering is complete.

Prerequisites

Root privileges are required. The examples below assume a server with two disks: /dev/sda (working) and /dev/sdb (failed). Adjust device names to match your setup.

Warning

Back up all important data before proceeding. Replacing a root disk is a high-risk operation. A mistake at any step can result in data loss or an unbootable system. Avoid using /dev/sdX device names in ZFS commands. Device names can change after a reboot. Use stable identifiers such as /dev/disk/by-id/ instead. The examples below use /dev/sdX for simplicity when working with partitioning tools. ZFS commands must always use /dev/disk/by-id/.

Step 1: Check the pool status

Before making any changes, check the current state of the pool:

zpool status -v

The output will show which disk is faulted and its identifier in the pool.

Step 2: Take the failed disk offline

If the disk is ONLINE but failing, take it offline before the physical replacement:

zpool offline rpool <failed-device>

ZFS will stop attempting to use the failing disk before the physical replacement. Replace <failed-device> with the identifier shown in zpool status -v. If the disk is already FAULTED or REMOVED, skip this step and proceed directly to Step 3.

Step 3: Replace the disk physically

If your server supports hot swap, replace the disk without shutting down.

Otherwise, power off the system:

poweroff

After installing the replacement disk, boot the server and confirm the new disk is visible:

lsblk -o NAME,SIZE,MODEL ls -l /dev/disk/by-id/

Use the by-id identifier of the new disk in the steps that follow.

Step 4: Determine the partition table type

Install gdisk if it is not already present:

apt install gdisk -y

Check the partition table type on the working disk:

gdisk -l /dev/sda

In the output, look for the Partition table scan section. For MBR the result will show MBR: MBR only and GPT: not present. For GPT it will show MBR: protective and GPT: present.

Step 5: Prepare and copy the partition table to the new disk

Most ZFS root setups use GPT partitioning. The MBR method is included for legacy systems.

GPT

Before proceeding, identify the /dev/sdX name that corresponds to the new disk, as partitioning tools require it:

lsblk -o NAME,SIZE,MODEL,SERIAL

Clear any old signatures from the replacement disk before copying the partition table:

wipefs -a /dev/disk/by-id/<new-disk>

Warning

wipefs -a permanently removes all filesystem and partition signatures from the disk. Make sure the correct disk identifier is specified before running this command.

The following command copies the partition table from /dev/sda (source) to /dev/sdb (destination):

sgdisk -R /dev/sdb /dev/sda

Warning

In sgdisk -R, the first argument is the destination disk and the second is the source. Running this command with the arguments reversed will overwrite the partition table on the working disk.

If the replacement disk is larger than the original, expand the GPT to use the full disk:

sgdisk -e /dev/sdb

Then assign a new unique UUID to the replacement disk:

sgdisk -G /dev/sdb

Warning

sgdisk -G assigns new UUIDs to all partitions on the replacement disk. If /etc/fstab contains UUID-based entries for any of these partitions, the system may fail to boot. After resilvering completes, verify that /etc/fstab uses /dev/disk/by-id/ identifiers rather than UUIDs.

Reload the partition table so the kernel picks up the new layout:

udevadm trigger udevadm settle

If the replacement disk was previously used in another ZFS pool, clear any old ZFS metadata to avoid conflicts:

zpool labelclear /dev/disk/by-id/<new-disk-partX> 2>/dev/null || true

Replace <new-disk-partX> with the actual ZFS partition identifier.

MBR

The following command copies the partition table from /dev/sda (source) to /dev/sdb (destination):

sfdisk -d /dev/sda | sfdisk /dev/sdb

If the new partitions are not visible in the system after copying, reload the partition table:

udevadm trigger udevadm settle

Step 6: Add the disk to the pool

Replace the faulted disk entry in the pool with the new disk. First, check the exact identifier of the failed disk as shown in the pool:

zpool status rpool

In the output, find the entry for the faulted disk under the pool's device list. It will appear as a full path, for example /dev/disk/by-id/ata-WDC_WD10_12345-part3, with a status of FAULTED, UNAVAIL, or OFFLINE. Use that path as <old-device> in the replace command:

zpool replace rpool <old-device> /dev/disk/by-id/<new-disk-part>

Replace <old-device> with the identifier of the faulted disk from the previous step. Replace <new-disk-part> with the by-id identifier of the replacement disk partition, using the same partition number as the working disk (for example, -part3 or -part4). To find the correct identifier, run ls -l /dev/disk/by-id/.

If the old disk is fully unavailable (UNAVAIL) and zpool replace returns an error, add the -f flag to force the replacement:

zpool replace -f rpool <old-device> /dev/disk/by-id/<new-disk-part>

After running zpool replace, confirm that resilvering has started and the new disk appears as ONLINE:

zpool status

Resilvering continues automatically in the background.

Step 7: Monitor resilvering

Track resilvering progress with:

zpool status -v

The output shows progress, speed, and estimated time remaining. Wait until the status shows state: ONLINE and resilvering is complete before proceeding. Depending on disk size, this may take hours.

Step 8: Verify the boot dataset

Before installing the bootloader, verify that the pool has the correct boot dataset configured:

zpool get bootfs rpool

The output should show a dataset path such as rpool/ROOT/debian. If the value is none or points to the wrong dataset, set it manually:

zpool set bootfs=rpool/ROOT/debian rpool

Replace rpool/ROOT/debian with the actual root dataset name on your system. To list available datasets, run zfs list.

Step 9: Install the bootloader

Install the bootloader on the replacement disk after resilvering completes. The system continues to run from the original disk during resilvering, so this step is safe to perform once the pool is healthy.

BIOS (Legacy)

grub-install /dev/disk/by-id/<new-whole-disk>

On some systems, grub-install may not accept a by-id path. In that case, replace /dev/disk/by-id/<new-whole-disk> with the corresponding device name, for example /dev/sdb.

UEFI

Mount the EFI partition from the replacement disk to a temporary directory before running grub-install. This avoids shadowing the currently active EFI partition:

mkdir -p /mnt/new_efi mount /dev/disk/by-id/<new-disk-part1> /mnt/new_efi

Replace <new-disk-part1> with the actual EFI partition identifier (typically -part1 or -part2; partition type EF00). Check with ls -l /dev/disk/by-id/ if unsure.

If the EFI partition is empty, copy the contents from the existing EFI partition before running grub-install:

cp -r /boot/efi/* /mnt/new_efi/

Install the bootloader:

apt install grub-efi-amd64 efibootmgr -y grub-install --target=x86_64-efi --efi-directory=/mnt/new_efi --bootloader-id=debian --recheck /dev/disk/by-id/<new-whole-disk> update-grub update-initramfs -u -k all

Replace --bootloader-id=debian with the name matching your distribution (for example, ubuntu or debian). Replace /dev/disk/by-id/<new-whole-disk> with the by-id identifier of the entire replacement disk, not a partition.

Running update-initramfs ensures that the initial ramdisk includes the current ZFS modules and recognizes the new pool layout. Without this step, the system may fail to boot after the replacement.

Unmount the EFI partition after installation:

umount /mnt/new_efi

Verify the EFI boot entries:

efibootmgr -v

Warning

On systems with a ZFS root, grub-install may fail or require additional flags depending on the GRUB version and system configuration. For example, some systems require installing GRUB with ZFS support modules or running the command from a chroot environment. If the command returns an error, consult your distribution's documentation for ZFS-specific GRUB installation instructions.

Info

On Proxmox VE, grub-install is disabled. Use proxmox-boot-tool instead. The example below uses /dev/sdb2 — replace it with the actual EFI partition on your system:

proxmox-boot-tool format /dev/sdb2 proxmox-boot-tool init /dev/sdb2

Conclusion

After installing the bootloader, reboot the server and verify that it boots normally. Run a scrub to check for any read/write errors that may have occurred during resilvering:

zpool scrub rpool

Then verify the pool status:

zpool status -v

The pool should be online with no errors. If any issues appear during the process, check the system logs with journalctl -xe for additional details.

Warning

Before discarding the failed disk that was removed in Step 3, reboot and verify that the system boots normally with the replacement disk. Keep the failed disk as a fallback until boot is confirmed.

VAT

  • Other

    Ex. VAT

    0%
  • austria

    Austria

    20%
  • Belgium

    Belgium

    21%
  • Bulgaria

    Bulgaria

    20%
  • Croatia

    Croatia

    25%
  • Cyprus

    Cyprus

    19%
  • Czech Republic

    Czech Republic

    21%
  • Denmark

    Denmark

    25%
  • Estonia

    Estonia

    22%
  • France

    France

    20%
  • Finland

    Finland

    24%
  • Germany

    Germany

    19%
  • Greece

    Greece

    24%
  • Hungary

    Hungary

    27%
  • Ireland

    Ireland

    23%
  • Italy

    Italy

    22%
  • Latvia

    Latvia

    21%
  • Lithuania

    Lithuania

    21%
  • Luxembourg

    Luxembourg

    17%
  • Malta

    Malta

    18%
  • Netherlands

    Netherlands

    21%
  • Poland

    Poland

    23%
  • Portugal

    Portugal

    23%
  • Romania

    Romania

    19%
  • Slovakia

    Slovakia

    20%
  • Slovenia

    Slovenia

    22%
  • Spain

    Spain

    21%
  • Sweden

    Sweden

    25%
  • USA

    USA

    0%
european
states
  • germany
  • Español
  • Italiano
  • Poland
  • Русский
  • Slovenski
  • Türkçe
  • ukraine
  • kingdom
  • French
  • Hrvatska
  • Other
  • Austria
  • Belgium
  • Bulgaria
  • Croatia
  • Cyprus
  • Czech Republic
  • Denmark
  • Estonia
  • Finland
  • France
  • Germany
  • Greece
  • Hungary
  • Ireland
  • Italy
  • Latvia
  • Lithuania
  • Luxembourg
  • Malta
  • Netherlands
  • Poland
  • Portugal
  • Romania
  • Slovakia
  • Slovenia
  • Spain
  • Sweden
  • USA