A udev rule lets WebHID apps reach your mouse without sudo. Here’s the whole setup — wired, wireless, and Bluetooth.
TL;DR — drop this in
/etc/udev/rules.d/70-webhid.rules, reload, replug. It covers every HID device on the machine:
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", TAG+="uaccess"Why your browser can’t see your mouse
Web apps that configure mice — button remapping, DPI, RGB, macros — talk to the device through WebHID, which reads /dev/hidraw* directly.
Out of the box, Linux hands those nodes to root:root with mode 0600. Your browser runs as your normal user, so it can’t open them. The app either shows no devices or only works when the browser is launched as root.
Running the browser with sudo “works”, but it’s the wrong fix. The right fix is a udev rule that grants your logged-in user access to that one device.
What you’ll need
- A Chromium-based browser — Chrome, Chromium, Brave, Edge, Vivaldi, Opera. Firefox’s WebHID support is partial and unreliable.
- Terminal access with
sudo. - Your mouse connected via at least one transport.
Applies to Ubuntu, TUXEDO OS, Pop!_OS, Debian, Linux Mint, and other systemd-based distros.
Step 1 — Identify your device
The matching style differs per transport, so use only the section you need.
Wired or USB dongle
lsusbFind your mouse in the list:
Bus 001 Device 005: ID 046d:c52b Logitech, Inc. Unifying ReceiverYour IDs are 046d (vendor) and c52b (product). Note them in lowercase — udev is case-sensitive.
Bluetooth
bluetoothctl devicesMap hidraw nodes to devices
Run this with the device connected. It tells you which node belongs to which device:
for h in /sys/class/hidraw/hidraw*; do
echo "== ${h##*/}"
cat "$h/device/uevent"
doneFor Bluetooth, also walk the parent chain:
udevadm info -a -n /dev/hidrawNBluetooth trap: BT HID devices usually have no idVendor/idProduct attributes. A USB-style rule silently never matches them. Look for HID_ID / HID_UNIQ in the uevent output and the parent’s KERNELS name in the udevadm walk — that’s your identifier.
Step 2 — Create the udev rule
sudo nano /etc/udev/rules.d/70-webhid.rulesEach line is independent, so include every transport your mouse supports.
USB — wired or dongle
# USB
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", TAG+="uaccess"Use ATTRS (plural) — the IDs live on the parent USB device, so ATTR alone won’t match.
Bluetooth / BLE
Match the parent’s kernel name. The .* absorbs a per-connection counter that changes on every reconnect:
# Bluetooth / BLE
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", KERNELS=="0005:3151:402C.*", TAG+="uaccess"Or match the stable HID identity from the uevent output:
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ENV{HID_ID}=="0005:00003151:0000402C", TAG+="uaccess"Why two different styles? The USB device exposes vendor/product attributes; the Bluetooth device genuinely doesn’t. Don’t “fix” one to look like the other — it will stop working.
Step 3 — Apply the rule
sudo udevadm control --reload-rules
sudo udevadm triggerThen physically unplug and replug the mouse, or toggle Bluetooth off and on. Existing nodes keep their old permissions until the device re-enumerates.
Step 4 — Verify it worked
for f in /dev/hidraw*; do echo "== $f"; getfacl -c "$f"; doneYou want a line like this on the right node:
user:yourname:rw-That’s the uaccess ACL. Now fully restart your browser and reload the app.
You can dry-run the rule before trusting it:
udevadm test /sys/class/hidraw/hidrawNTroubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Rule never matches | Uppercase hex in IDs | Use lowercase: 046d, not 046D |
| Rule never matches | File in /lib/udev/rules.d/ | Move to /etc/udev/rules.d/ |
| USB rule never matches | Used ATTR not ATTRS | Use ATTRS — IDs are on the parent device |
| BT rule never matches | Matched idVendor, absent on BT | Use KERNELS or ENV{HID_ID} |
| BT rule breaks on reconnect | Hard-coded the .NNNN suffix | Glob it: 0005:3151:402C.* |
| Nothing happens | Didn’t replug the device | Replug, or toggle Bluetooth |
| No ACL after replug | uaccess needs a local session | Use MODE="0660", GROUP="plugdev" |
Works only under sudo | Rule isn’t matching | Recheck IDs against udevadm info -a |
| Firefox can’t see it | Partial WebHID support | Use Chrome/Chromium/Brave/Edge |
| Snap browser can’t see it | Snap confinement | snap connect firefox:joystick |
Watch udev process rules live:
sudo udevadm control --log-priority=debug
sudo udevadm monitor --udev --subsystem-match=hidrawBrowser-side errors: open chrome://device-log.
Bluetooth caveat
Many mice expose fewer HID collections over Bluetooth than over USB — the vendor config interface is often USB-only. If the app connects over Bluetooth but finds no settings to change, that’s the firmware, not your rule. Test over USB to confirm.
Why not just run the browser as root?
sudo chrome works, but your browser profile, cache, and keyring can end up root-owned and cause confusing problems later. uaccess is scoped to one device and one logged-in user, with no side effects.
Security
uaccess grants your user read/write on the device node. The broad KERNEL=="hidraw*" rule does that for all HID devices. Neither grants root. To narrow it, keep the specific VID/PID or HID_ID match instead.
Uninstall
sudo rm /etc/udev/rules.d/70-webhid.rules
sudo udevadm control --reload-rules
sudo udevadm triggerThen replug the device.
Quick reference
# List USB devices
lsusb
# Map hidraw nodes to devices
for h in /sys/class/hidraw/hidraw*; do echo "== ${h##*/}"; cat "$h/device/uevent"; done
# Full attribute walk for a node
udevadm info -a -n /dev/hidrawN
# Apply rules
sudo udevadm control --reload-rules
sudo udevadm trigger
# Verify ACLs
getfacl -c /dev/hidrawN