Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save microraptor/be170ea642abeb937fc030175ae89c0c to your computer and use it in GitHub Desktop.
Save microraptor/be170ea642abeb937fc030175ae89c0c 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].
#
# This file should be placed at:
# /etc/udev/rules.d/80-mount-usb-to-media-by-label.rules
# Note: Beware of using only Unix line endings and not Windows ones.
# A 'CONFIG' USB key can be used to install this file.
#
# 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 or 'hassos-data' partition.
# 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 on line 70.
#
# Note 4:
# If using a kernel with the ntfs3 module (running 'modinfo ntfs3' in a shell is not returning an error),
# line 102 can be uncommented to get read/write support for NTFS partitions.
#
# Note5:
# If only partitions with a specific label should be mounted,
# uncomment and edit line 83.
#
# Source of inspiration:
# https://www.axllent.org/docs/auto-mounting-usb-storage/
#
# Useful links:
# https://wiki.archlinux.org/index.php/Udev
#
# Discussions and previous versions:
# https://community.home-assistant.io/t/258406
# https://gist.github.com/eklex/c5fac345de5be9d9bc420510617c86b5
# https://gist.github.com/zeehio/7c67d531236e39496c39b3c5c3b3f268
#
# See this variation for mounting internal partitions instead of USB external ones:
# https://gist.github.com/Deckoz2302/489e3600bb9facbb3be65bd738e27d1c
#
# 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"
# Uncomment and edit the line below, if only partitions with a specific label should be mounted
# ENV{ID_FS_LABEL}!="myPartitionLabel", GOTO="abort_rule"
# Exit if this is the 'CONFIG' USB key or 'hassos-data' partition
ENV{ID_FS_LABEL}=="CONFIG", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-data", 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}"
# Set fstype option (might be overwritten in the next code paragraph)
ENV{fstype}="-t auto"
# If the filesystem is ntfs, use the ntfs3 driver, so we get read/write support
# Home Assistant Operating System 8.0 or later required (linux kernel 5.15 for the ntfs3 module)
# Only uncomment the line below, if running 'modinfo ntfs3' in a shell is not returning an error
# ENV{ID_FS_TYPE}=="ntfs", ENV{fstype}="-t ntfs3"
# 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 %E{fstype} --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"
@microraptor
Copy link
Author

microraptor commented Nov 14, 2024

Please take a look at the options and comments within the file before using it. The file can be installed on the Home Assistant host system using one of two methods:

The Home Assistant host system can be rebooted in the current UI here:
Settings -> System -> (Power Button Icon) -> Advanced options -> Reboot system

Note: The read and write speeds will probably be faster on most systems, if the external drive is formatted with a EXT4 partition instead of NTFS.

See discussions here:
https://community.home-assistant.io/t/258406
https://gist.github.com/eklex/c5fac345de5be9d9bc420510617c86b5
https://gist.github.com/zeehio/7c67d531236e39496c39b3c5c3b3f268

This is a fork from the gist of eklex and zeehio linked above. It adds:

  • An option to mount only partitions with a specific label
  • An option to mount NTFS read/write as implemented by zeehio (uncomment that line only, if modinfo ntfs3 does not return an error)
  • 'hassos-data' partition won't be mounted
  • Some minor documentation

@felipecrs
Copy link

Thank you very much, @microraptor. I have put this into a "guide" here.

@IMNotMax
Copy link

IMNotMax commented Apr 2, 2025

Hi, I made some improvements for my use case.

My HAOS runs on a raspberry pi 4.
Boots on a SDCard BUT Runs on a USB SSD Drive (the SDCard just has the boot partition)
My issue was a lot of folders were mounted even with the improved rules

Below, what is working for me.

First, I had to specify more Partition labels in the section used for the CONFIG USB key and the hassos-data

# Exit if this is the 'CONFIG' USB key or 'hassos-data' partition
ENV{ID_FS_LABEL}=="CONFIG", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-system0", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-system1", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-kernel0", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-kernel1", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-overlay", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-boot", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-data", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-var", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-tmp", GOTO="abort_rule"
ENV{ID_FS_LABEL}=="hassos-bootstate", GOTO="abort_rule"

then I had to specify the partuuid too because, as a USB drive, even if it's blocked with the part labels, the USB-SDB1 to 5 were mounted


# Exit if this has the PARTUUID values
ENV{ID_PART_ENTRY_UUID}=="b3dd0952-733c-4c88-8cba-cab9b8b4377f", GOTO="abort_rule"  
ENV{ID_PART_ENTRY_UUID}=="26700fc6-b0bc-4ccf-9837-ea1a4cba3e65", GOTO="abort_rule"  
ENV{ID_PART_ENTRY_UUID}=="8d3d53e3-6d49-4c38-8349-aff6859e82fd", GOTO="abort_rule"  
ENV{ID_PART_ENTRY_UUID}=="fc02a4f0-5350-406f-93a2-56cbed636b5f", GOTO="abort_rule"  
ENV{ID_PART_ENTRY_UUID}=="a3ec664e-32ce-4665-95ea-7ae90ce9aa20", GOTO="abort_rule"  
ENV{ID_PART_ENTRY_UUID}=="33236519-7f32-4dff-8002-3390b62c309d", GOTO="abort_rule"  
ENV{ID_PART_ENTRY_UUID}=="f1326040-5236-40eb-b683-aaa100a9afcf", GOTO="abort_rule"

Now, only USB drives are mounted, and I don't have to manage a lot of folders in /mnt/data/supervisor/media/

(another improvement I made, not directly related to the rules, is to add part labels to my drives, better to have "USB-120GO" as a folder than "usb-sdc1"
e2label /dev/sda1 DATA works good, and tune2fs -L DATA /dev/sda1 too as specified in the comment from @felipecrs blakeblackshear/frigate#4644 (comment) above)

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