Skip to content

Instantly share code, notes, and snippets.

@axzxc1236
Last active January 12, 2025 19:28
Show Gist options
  • Save axzxc1236/fc74b8dc94b10a3a2bc3fd9b3251aaba to your computer and use it in GitHub Desktop.
Save axzxc1236/fc74b8dc94b10a3a2bc3fd9b3251aaba to your computer and use it in GitHub Desktop.
How to mount ZFS pools thats on USB drives automatically.

I know there are a lot of tutorials on mounting ZFS automatically already, but that didn't work for me.

My situation:
I have a USB DAS(Direct-Attached Storage) that is connected to my NAS.

Why didn't the tutorials on the internet worked for me:
Systemd service files that comes with ZFS won't wait for USB devices.

Solution:
Create a service that can wait for my DAS to be recognized by Linux and then mount my ZFS pool.

Disclaimer:
1. nano is my personal preference, you can use your text editor as well.
2. Yes, you can change script and service name if you know how to do it. 3. There are no warranty of any kind, and this guide shouldn't break your system.


  1. Identify your disks
    What model of hard drives/SSDs are you using?
    In my situation I have 8 TOSHIBA MG09ACA18TE hard drives
    I can check
    /dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE*
    to see if the disks are connected or not
    e.g. ls /dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE*
    (The above command shows 24 results, including -part1 and -part9)
    So I can use
    test "$(ls /dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE* | wc -l)" = "24" && echo We are ready
    to check if disks are picked up and ready for ZFS pool import

  1. create /waitZFSMount.sh
    (1) sudo nano /waitZFSMount.sh
    (2) paste these scripts
#! /bin/bash
while [ ! -d /sys/module/zfs ];
do
  sleep 1;
done
echo zfs module is loaded
while [ ! "$(ls /dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE* | wc -l)" = "24" ];
do
  sleep 1
done
echo USB disks are ready 

(3) Make sure to edit conditions
for checking disks, you (random person on the Internet) probably don't use TOSHIBA_MG09ACA18TE hard drives.
(If you are not sure, go back to step 1, now!)
(4) Save the script with Ctrl+X
(5) sudo chmod 700 /waitZFSMount.sh
(6) try if the script works (sudo /waitZFSMount.sh)
* the script should exit itself instantly if you are ready for importing/mounting.


  1. create mounting service
    (1) sudo systemctl edit --full --force zfs-custom-mount.service
    (2) paste service file
[Unit]
Description=Mount ZFS filesystems (custom edition)
Documentation=man:zfs(8)
DefaultDependencies=no
After=systemd-udev-settle.service
After=cryptsetup.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/waitZFSMount.sh
ExecStart=/usr/bin/zpool import -a
ExecStart=/usr/bin/zfs load-key -a
ExecStart=/usr/bin/zfs mount -a

[Install]
WantedBy=multi-user.target

(3) Decide if it needs change or not
In my case I used encrypted dataset and key file, if you don't need these you can probably remove
After=cryptsetup.target
ExecStart=/usr/bin/zfs load-key -a
ExecStart=/usr/bin/zfs mount -a
(4) Save script to ctrl+x
(5) Try it with sudo systemctl start zfs-custom-mount
(If your ZFS pool is already running, you can unmount/export with sudo zpool export (pool name)
(6) what does systemctl status zfs-custom-mount say? I hope it runs.
(7) Make it run at start up by doing sudo systemctl enable zfs-custom-mount.service
(8) reboot and see what happens, try zfs get mounted
(9) If the script is stuck, try running sudo /waitZFSMount.sh
If there is no output, ZFS module is not loaded automatically, you need to make sure zfs module loads at boot
e.g. echo "zfs" | sudo tee /etc/modules-load.d/zfs.conf


I hope it helps

@exenza
Copy link

exenza commented May 8, 2024

thanks this worked for me on pi5 running raspbian!

@exenza
Copy link

exenza commented May 8, 2024

I've scripted it so doesn't requires manual steps, please note that my bash is on /usr/bin/bash so whoever may want to use this script should change it to desired bash path:

#! /usr/bin/bash
echo "###### Z F S ######"
echo "Identify the disks id pattern, i.e. 'usb-JMicron_Generic_DISK0*'"
echo ""
read -p "Press any key to list disks by id..."
ls /dev/disk/by-id/
read -p "pattern=" pattern
echo "Counting number of drives found with $pattern"
count=`ls /dev/disk/by-id/$pattern | wc -l`
echo "$pattern returned $count drives, is this correct?"
select yn in "Yes" "No"; do
    case $yn in
        Yes ) echo "Generating autommount script...";break;;
        No ) echo "Exiting, start this script again";exit;;
    esac
done
echo '#! /usr/bin/bash
while [ ! -d /sys/module/zfs ];
do
  sleep 1;
done
echo zfs module is loaded
while [ ! "$(ls /dev/disk/by-id/'$pattern' | wc -l)" = "'$count'" ];
do
  sleep 1
done
echo USB disks are ready' > waitZFSMount.sh
chmod +x waitZFSMount.sh
cp waitZFSMount.sh /
echo "Generated script and copied to root /"
echo "Loading service..."
echo "\
[Unit]
Description=Mount ZFS filesystems (custom edition)
Documentation=man:zfs(8)
DefaultDependencies=no
After=systemd-udev-settle.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/waitZFSMount.sh
ExecStart=/usr/bin/zpool import -a

[Install]
WantedBy=multi-user.target" > /etc/systemd/system/zfs-custom-mount.service
echo "Created /etc/systemd/system/zfs-custom-mount.service"
echo `systemctl daemon-reload`
echo `systemctl enable /etc/systemd/system/zfs-custom-mount.service`
echo `systemctl start zfs-custom-mount`
echo `systemctl status zfs-custom-mount`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment