Skip to content

Instantly share code, notes, and snippets.

@eklex
Last active February 4, 2024 18:36
Show Gist options
  • Star 59 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save eklex/c5fac345de5be9d9bc420510617c86b5 to your computer and use it in GitHub Desktop.
Save eklex/c5fac345de5be9d9bc420510617c86b5 to your computer and use it in GitHub Desktop.
udev rule for Home Assistant OS (hassio) to mount USB drives into the Supervisor Media directory
#
# udev rule
# Mount USB drive to the media directory using the partition name as mount point
#
# Description:
# Created for Home Assistant OS, this rule mounts any USB drives
# into the Hassio media directory (/mnt/data/supervisor/media).
# When a USB drive is connected to the board, the rule creates one directory
# per partition under the media directory. The newly created partition is named
# as the partition name. If the partition does not have a name, then the following
# name format is used: "usb-{block-name}" where the block name is sd[a-z][0-9].
#
# Note 1:
# The rule name is always prefixed with a number. In this case, the rule uses 80.
# This represents the order of the rule when multiple rules exists in udev.
# Low numbers run first, high numbers run last. However, low numbers do not have all
# the facilities than high numbers may have.
# For this rule to run properly, use numbers equal or greater than 80.
#
# Note 2:
# This rule will skip mounting the 'CONFIG' USB key.
# https://github.com/home-assistant/operating-system/blob/dev/Documentation/configuration.md
#
# Note 3:
# This rule will mount the OS partitions if the OS is sorted on a USB drive (i.e. USB booting).
# To prevent this issue from happening, update the rule to skip the booting USB drive.
# See the CAUTION message below.
#
# Source of inspiration:
# https://www.axllent.org/docs/auto-mounting-usb-storage/
#
# Useful links:
# https://wiki.archlinux.org/index.php/Udev
#
# udev commands:
# - Restart udev to reload new rules:
# udevadm control --reload-rules
# - List device attributes of sdb1:
# udevadm info --attribute-walk --name=/dev/sdb1
# - List environment variables of sdb1:
# udevadm info /dev/sdb1
# - Trigger add/remove event for sdb1:
# udevadm trigger --verbose --action=add --sysname-match=sdb1
# udevadm trigger --verbose --action=remove --sysname-match=sdb1
#
# Filter on block devices, exit otherwise
# CAUTION: Change to 'sd[b-z][0-9]' if booting from a USB drive (e.g.: sda)
KERNEL!="sd[a-z][0-9]", GOTO="abort_rule"
# Skip none USB devices (e.g.: internal SATA drive)
ENV{ID_PATH}!="*-usb-*", GOTO="abort_rule"
# Import the partition info into the environment variables
IMPORT{program}="/usr/sbin/blkid -o udev -p %N"
# Exit if partition is not a filesystem
ENV{ID_FS_USAGE}!="filesystem", GOTO="abort_rule"
# Exit if this is the 'CONFIG' USB key
ENV{ID_FS_LABEL}=="CONFIG", GOTO="abort_rule"
# Get the partition name if present, otherwise create one
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="usb-%k"
# Determine the mount point
ENV{mount_point}="/mnt/data/supervisor/media/%E{dir_name}"
# Mount the device on 'add' action (a.k.a. plug the USB drive)
ACTION=="add", RUN{program}+="/usr/bin/mkdir -p %E{mount_point}", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=no --collect $devnode %E{mount_point}"
# Umount the device on 'remove' action (a.k.a unplug or eject the USB drive)
ACTION=="remove", ENV{dir_name}!="", RUN{program}+="/usr/bin/systemd-umount %E{mount_point}", RUN{program}+="/usr/bin/rmdir %E{mount_point}"
# Exit
LABEL="abort_rule"
@jane-t
Copy link

jane-t commented Jul 16, 2022

I am have the same problem as https://gist.github.com/eklex/c5fac345de5be9d9bc420510617c86b5?permalink_comment_id=4104054#gistcomment-4104054

Running on HA OS on a DELL the drive names are mounted and appear in the Media folder, but there are no contents. I have tried FAT32 and NTFS format devices. When the drives are removed the names are not removed from the Media folder. Current versions
Home Assistant 2022.7.5 Supervisor 2022.07.0 Operating System 8.2 Frontend 20220707.1 - latest

@ThinkTank0790
Copy link

ThinkTank0790 commented Aug 10, 2022

@Moondevil-ha - Thank you documenting this so good. Apparently, I'm too dumb to make this work even with such extensive documentation. Here are the steps i followed.

  • Created the 80-rules files. Imported them into the configuration by rooting into HA CLI (Connected Monitor & keyboard to HA Blue)
  • Created the secondary 80-additional storage rule file since I'm planning to mount a Seagate 5TB ext4 partitioned HDD to my HA Blue.
  • Both the files have been imported successfully and I'm able to find them in /etc/udev/ folder.

But I don't see the /dev/sda2 drive mounted to /mnt/...../media folder. Have restarted, rebooted the host with no luck!

Running HA Core: 2022.8.2

Can you/someone help me out please?

@paoloantinori
Copy link

monitor udev events when interacting with peripherals
sudo udevadm monitor --environment --udev
simulate hw events to verify the triggering of rules
udevadm test --action=add /devices/pci0000:00/0000:00:14.0/usb2/2-4

@Moondevil-ha
Copy link

Moondevil-ha commented Aug 11, 2022 via email

@bighippo999
Copy link

I read the note on changing sda to sdb to skip mounting the OS if booting from USB.
I don't really know why I did it, but I moved HA data to it's own USB on RPi4. So it's not the whole OS. While the above change would work, I fear that sda may not permanently be the data partition.
So instead I added the line:
ENV{ID_FS_LABEL}=="hassos-data", GOTO="abort_rule"
To line 63. So it now skips mounting a CONFIG and/or hassos-data partition.

It feels like a better solution for me. May help someone else.

@unalgunay
Copy link

Thanks for your feedback, worked for me

@my-machines
Copy link

Thank you @eklex for this great rule that works very nicely.
For some unrelated reasons and to test something I need to remove the rule, but I don't know how. Can someone explain to me how to remove this rule?
Thank you in advance.

@my-machines
Copy link

ok, i did it via ssh as root to HA and following command:
# rm /etc/udev/rules.d/80-mount-usb-to-media-by-label.rules

@sagarspatil
Copy link

These were awesome instructions, thank you @eklex for posting them.

I wanted to share a slight modification to these instructions that was useful for my specific use case that may benefit others. I have Home Assistant OS running on a Proxmox VM and I wanted to add a second VirtIO disk for Frigate to use.

This really does give the best of both worlds - if you want to keep the fully managed Home Assistant OS (and retain supported installation status!) but you want to mount a second disk.

Here is what I did and what you can do if you want to get this working:

HOW TO ADD A SECOND VIRTUAL DISK TO HOME ASSISTANT OS RUNNING AS A VIRTUAL MACHINE:

  1. Shut down the VM and add a VirtIO disk in Proxmox (or your prefered virtualization software) of your desired size
  2. Start up the VM and login to the core OS. On Proxmox you can use NoVNC to get to the shell and then type "login" at the prompt which then gets you into the OS. **Another path is to SSH to port 22222 if you have the Port 22222 add-on installed - ** I did this since I already had it configured and it was just easier than messing with NoVNC as you can copy/paste/SCH in/etc.
  3. fdisk /dev/vdb (mine appeared as vdb. To verify, do fdisk --list and look for your new disk)
  4. type "n" to add a new partition. All default options are fine. Make sure to use "w" at the end to commit your changes
  5. mkfs.ext4 /dev/vdb1 to format the new partition
  6. lsblk -f and write down the UUID
  7. vi /etc/udev/rules.d/80-mount-additional-storage.rules (if you're not comfortable with vi and if you have port 22222 access, use your favorite SCP client to log in and edit the file locally, then upload. I prefer Nano but it doesn't come with Home Assistant OS)
  8. Insert the following. Note that I changed my mount directory to be Frigate since this is where Frigate saves its media files. In any case, if you have an existing folder here, please delete or rename it to something else.
KERNEL!="vdb[0-9]", GOTO="abort_rule"

ACTION=="add", RUN{program}+="/usr/bin/mkdir -p /mnt/data/supervisor/media/frigate", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=no --collect /dev/disk/by-uuid/<your UUID goes here>	/mnt/data/supervisor/media/frigate"
ACTION=="remove", RUN{program}+="/usr/bin/systemd-umount /mnt/data/supervisor/media/frigate", RUN{program}+="/usr/bin/rmdir /mnt/data/supervisor/media/frigate"

LABEL="abort_rule"
  1. Reboot your system
  2. Browse to the path within /media that you designated, keeping in mind that your Docker path will be slightly different from the path at the supervisor level. For example /mnt/data/supervisor/media/frigate will appear as /media/frigate. Make sure you see the folder.
  3. Run df -h and look for that same folder. You should see it now attached to a new disk with a different size/different free space from your boot drive.
  4. Now try copying some files in there and do df -h again, you should see the space on the new drive shrinking and space on the boot drive freeing up.

Hope this helps someone.

Step 8.5: Remove the USB drive that has the udev folder/file or simply delete the folder/file. I used the same USB drive to store CONFIG for HA that allows me to login as root and to store udev file. Whenever I was rebooting, it simply kept re-writing the udev file (original) with the one I had modified.

@HolgerM1
Copy link

Hi, anybody a suggestion for a total noob how to run this? I have HassOS on an external SD card on an Minisforum J4125 and would like to mount an ext. HDD (ntfs).

@codyrocco
Copy link

codyrocco commented Jan 6, 2023

In HAOS 9.4 NTFS isn't present either as module, nor builtin, if HAOS barebone is used. In supervised mode, every filesystem supported by kernel will be available to HAOS

@zeehio
Copy link

zeehio commented Jan 6, 2023

In HAOS 9.3 NTFS isn't present either as module, nor builtin, if HAOS barebone is used. In supervised mode, every filesystem supported by kernel will be available to HAOS

I am on 9.4 and I see the ntfs.ko module (provides read only) and the ntfs3.ko module (providing read and write support).

Both fs drivers are designed for NTFS partitions, the ntfs read only is chosen by default because it has the same name as the filesystem)

In this older message I mention I was able to use the ntfs3 driver on HAOS8.x https://gist.github.com/eklex/c5fac345de5be9d9bc420510617c86b5?permalink_comment_id=4167754#gistcomment-4167754. Why do you say HAOS9.3 does not have the ntfs3 module?

@codyrocco
Copy link

codyrocco commented Jan 6, 2023

In HAOS 9.3 NTFS isn't present either as module, nor builtin, if HAOS barebone is used. In supervised mode, every filesystem supported by kernel will be available to HAOS

I am on 9.4 and I see the ntfs.ko module (provides read only) and the ntfs3.ko module (providing read and write support).

Both fs drivers are designed for NTFS partitions, the ntfs read only is chosen by default because it has the same name as the filesystem)

In this older message I mention I was able to use the ntfs3 driver on HAOS8.x https://gist.github.com/eklex/c5fac345de5be9d9bc420510617c86b5?permalink_comment_id=4167754#gistcomment-4167754. Why do you say HAOS9.3 does not have the ntfs3 module?

I corrected previous message, 9.4 version also.
Using https://github.com/home-assistant/operating-system/releases/download/9.4/haos_generic-x86-64-9.4.img.xz, written with balena etcher, on an i5-7500t device, no ntfs module inside OS.
Modprobe will generate errors, ran in ssh on port 22222. Also, nothing in modules.builtin (a btrfs built as module is present in /var/lib/modules 🙂)
Tried to recompile from source, but there's only ntfs-3g. Make menuconfig in buildroot isn't allowing to select ntfs3.

@codyrocco
Copy link

i built a custom HAOS< extracted some modules i need, ntfs, ntfs3, fuse, exfat, aqc111. didn't suceeded to load ntfs module at HAOS start, via udev (maybe someone have a better idea), but at homeassistant container start (minor inconvenient here, i must re-plug an existent usb drive or call a service to repeat the mount action, also via udev)
the script here is working perfectly (just need to restart samba addon, or even entire homeassistant, for the usb drive content to be available in media folder).
main drawback is that a recompile is required every HAOS update (~1-1.30 hr of work in a VM)

@PeteDenmark
Copy link

PeteDenmark commented Feb 5, 2023

So excuse the newbie question, but i have both a M.2 disc and an SSD i my Intel NUC. Home Assistant is on the M.2 disc.

HA is installed on sdb 1 through 7, so if i want to omit sbd discs to be mouted is it ok to split the KERNEL! udev rules into two?

Like:

KERNEL!="sd[c-z][0-9]", GOTO="abort_rule"
KERNEL!="sd[a][0-9]", GOTO="abort_rule"

and the just delete:
ENV{ID_PATH}!="*-usb-*", GOTO="abort_rule"

In order for my internal SATA SSD on sda 1 and 2 to be mounted?

@hulkhaugen
Copy link

I've been using this with great success for a couple of years, but now I've messed it up somehow. The folder /media/usb-sdb1 is still there, but is now a folder on the internal hdd instead of the usb hdd and it's pretty much empty. I guess it's been re-generated by one of my add-ons that uses that folder. How can i troubleshoot this? I can see that the drive is still attached in my HA hw info, but it's apparently not mounted. I want to confirm if the rule is still present, and if something is preventing it from mounting, or if i just need to re-apply it...

@PeteDenmark
Copy link

I've been using this with great success for a couple of years, but now I've messed it up somehow. The folder /media/usb-sdb1 is still there, but is now a folder on the internal hdd instead of the usb hdd and it's pretty much empty. I guess it's been re-generated by one of my add-ons that uses that folder. How can i troubleshoot this? I can see that the drive is still attached in my HA hw info, but it's apparently not mounted. I want to confirm if the rule is still present, and if something is preventing it from mounting, or if i just need to re-apply it...

Check this tutorial out, on how to access your root of Home Assistant to see if the drive is mounted.
https://www.youtube.com/watch?v=CHvBzX41-Ag&t=507s

Sometimes HA is really strange when it comes to the media file system. Sometimes it places files in (root) /media, and sometimes in config/media.

Sometimes a reboot of the host helps. Also - if you are using samba, check if you can see your files through samba share.

@hulkhaugen
Copy link

I've been using this with great success for a couple of years, but now I've messed it up somehow. The folder /media/usb-sdb1 is still there, but is now a folder on the internal hdd instead of the usb hdd and it's pretty much empty. I guess it's been re-generated by one of my add-ons that uses that folder. How can i troubleshoot this? I can see that the drive is still attached in my HA hw info, but it's apparently not mounted. I want to confirm if the rule is still present, and if something is preventing it from mounting, or if i just need to re-apply it...

Check this tutorial out, on how to access your root of Home Assistant to see if the drive is mounted. https://www.youtube.com/watch?v=CHvBzX41-Ag&t=507s

Sometimes HA is really strange when it comes to the media file system. Sometimes it places files in (root) /media, and sometimes in config/media.

Sometimes a reboot of the host helps. Also - if you are using samba, check if you can see your files through samba share.

Yes I have samba, and yes I can find that folder, but it's empty apart from some empty folders. I also have a storage sensor that used to say 4TB free space, now it says 68 GB free space, suggesting that the usb-sdb1 is mounted on the internal SSD instead of the external usb hdd. I have tried a reboot of the host, but no cigar. My plan next is to disable all add-ons that might be using the usb-sdb1 destination, and then delete that empty folder. Reboot the host and see if it mounts correctly. If that doesn't work, i'll try to apply the udev rule again I guess. I'm not at home and thus not able to access the server atm, but will be this weekend...

@hulkhaugen
Copy link

hulkhaugen commented Mar 3, 2023

Ok, so since my drive was no longer available, I've tried some things:

  1. Disabled all apps using the usb, and deleted the new empty usb-sdb1 folder on the internal drive. Rebooted. No usb-sdb1 or similar folders to be found after reboot.
  2. Setup SSH access to Home Assistant OS (Not Core) on port 22222. Found the 80-mount-usb-to-media-by-label.rules rule file at /etc/udev/rules.d and opened it up in vi to be sure it wasn't empty. Didn't read it end-to-end, but it looked familiar so I'm assuming it's working. Dunno if it has to be enabled or activated somehow?
  3. Disconnected the drive, and connected it to my Windows PC. It did show up in Diskmanager, but it's making some rather high clicking sounds every now and then. Assuming it's dead.
  4. To be sure, I installed Raspbian on a RPi i had lying around. Booted it up and viola, still the clicking sounds and a few errormeassages at boot related to sda1. However, my 5TB usb hdd was right there on the desktop. I tried playing some video files, no problems what-so-ever.

Sooo...what might be causing this drive to not mount on my HA setup?

EDIT: I connected it back, and sure, usb-sdb1 re-appeard in my media directory. I had to reboot the host to get the content back. But I think my HDD is dying, even if it's only 1 year old, and not very much i/o.

@sumnerma
Copy link

@jane-t Did you ever get your issue sorted? I'm having the same problem

@IngoEF
Copy link

IngoEF commented Jan 7, 2024

Hi,
this might have been a well usable solution, but for me it's not working (Raspberry3, HASSIO version 11.3 docker edition)
After creating the rule in /lib/udev/rules.d and trying the udevadm commands in CLI I was informed this way: zsh: command not found: udevadm. Additionally, the added file disappeared after the next reboot
What is going wrong here?

In the meantime here is some more which might be a solution but I didn't get it working.

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