Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SirGoodenough/7283825fa33206b8def8543b6b2a1149 to your computer and use it in GitHub Desktop.
Save SirGoodenough/7283825fa33206b8def8543b6b2a1149 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[b-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"
@SirGoodenough
Copy link
Author

from https://gist.github.com/zeehio on May 15, 2022

Here is a possible explanation and a solution for those of you who can't write to the mounted disks (@AlRiachi). I guess you are using NTFS partitions. I had the same problem as you have and this solution worked for me.

There are three NTFS drivers:

One is named "ntfs", it exists since ~2001 and it provides read only support. This is the driver you are probably using. You can verify this by looking at the output of the mount | grep ntfs command when your usb drive is mounted, you should see at least one line that includes type ntfs.
Another driver is named "ntfs-3g", it is implemented as a "filesystem in user space" or "fuse". It provides read and write support, but since it is fuse it has larger overhead than other filesystem drivers AND it is not always installed (for instance it is not available on Home Assistant OS).
There is a third driver, named "ntfs3", implemented in the kernel (not as fuse) and introduced far more recently, in Linux 5.15. If you have the upcoming Home Assistant OS 8.0 or later, then you will have Linux 5.15 and this driver installed. I had to enable the beta channel to get it installed today, but it's becoming available soon for everyone I guess. This driver provides read and write support for NTFS partitions!

Since ntfs filesystems now have two drivers in the kernel (ntfs and ntfs3) the autodetection has to choose one. By default they all still use ntfs, but I guess they tools will update and change to the other driver, or maybe in the future the ntfs3 driver will replace the older ntfs driver. We'll see.

So, if you are using Home Assistant OS 8.0 or later, which includes the linux kernel 5.15, then you can modify the udev rules above to use the newer ntfs3 driver. Here are the changes I made to the file above:

Determine the mount point

ENV{mount_point}="/mnt/data/supervisor/media/%E{dir_name}"

If filesystem is ntfs, use the ntfs3 driver, so we get rw support

Home Assistant Operating System 8.0 or later required (linux kernel 5.15)

ENV{ID_FS_TYPE}=="ntfs", ENV{fstype}="-t ntfs3"
ENV{ID_FS_TYPE}!="ntfs", ENV{fstype}="-t auto"

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}"

As you can see, I first define an environment variable that specifies that if the filesystem is ntfs then the environment variable contains "-t ntfs", otherwise it uses "-t auto". Afterwards, in the action line, I pass the value of that environment variable as an argument to the systemd-mount command (using %E{fstype}), so it will use the autodetection by default unless the partition is ntfs, where it will use the ntfs3 driver I explicitly gave above.

The main caveat of this change is that it only works on linux kernels >= 5.15, and to be precise we would need to check that modinfo ntfs3 does not return an error to ensure that the driver is installed. (I just confirmed the driver is available on Home Assistant OS 8.0)

I put my changes here https://gist.github.com/zeehio/7c67d531236e39496c39b3c5c3b3f268 but once Home Assistant OS 8.0 becomes available and a large fraction of users have updated to it I would suggest @eklex to merge my suggestion here, if he likes.

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