USB Keyboard Not Working in Dracut When Connected via Thunderbolt Dock

My USB keyboard stopped working during the Dracut initramfs phase (e.g., at the LUKS password prompt) when connected through a Thunderbolt dock. It worked fine in GRUB, in GNOME, and when plugged directly into the laptop. It had also worked through the dock before.

Why It Broke

GRUB is probably using UEFI/BIOS USB legacy emulation and doesn’t need the Thunderbolt controller at all. Dracut uses the real kernel driver stack, so the Thunderbolt controller needs to be initialized and authorized before the keyboard becomes visible.

Checking the Thunderbolt security level:

$ cat /sys/bus/thunderbolt/devices/domain0/security
user

The user level requires explicit device authorization. In GNOME, boltd handles this automatically. In Dracut, nothing does. Previously the security level was none, but a firmware update changed it to user.

IOMMU DMA protection is still active independently:

$ cat /sys/bus/thunderbolt/devices/domain0/iommu_dma_protection
1

Why Not Boot ACL?

The ideal fix would be to enroll the dock in the firmware’s Boot ACL — pre-authorized devices stored in UEFI NVRAM that are authorized before the OS loads. However, boltctl domains showed bootacl: 0/0 — the firmware doesn’t support it.

The Fix: A Dracut-Only Udev Rule

The solution is a udev rule that auto-authorizes Thunderbolt devices during the initramfs phase only. We don’t want this rule in the running system, as it would bypass boltd’s authorization logic in GNOME. The clean way is a small dracut module that carries the udev rule inside the initramfs.

Create the module directory and files:

$ sudo mkdir -p /usr/lib/dracut/modules.d/99thunderbolt-auth

$ sudo tee /usr/lib/dracut/modules.d/99thunderbolt-auth/99-thunderbolt-auto-auth.rules <<'EOF'
ACTION=="add", SUBSYSTEM=="thunderbolt", ATTR{authorized}=="0", ATTR{authorized}="1"
EOF

$ sudo tee /usr/lib/dracut/modules.d/99thunderbolt-auth/module-setup.sh <<'EOF'
#!/bin/bash
check() { return 0; }
depends() { return 0; }
install() {
    inst_simple "$moddir/99-thunderbolt-auto-auth.rules" \
        /etc/udev/rules.d/99-thunderbolt-auto-auth.rules
}
EOF

$ sudo chmod +x /usr/lib/dracut/modules.d/99thunderbolt-auth/module-setup.sh

Create the dracut config at /etc/dracut.conf.d/thunderbolt.conf:

add_dracutmodules+=" thunderbolt-auth "

Note that dracut module names in config files omit the numeric prefix — the directory is 99thunderbolt-auth but is referenced as thunderbolt-auth.

Rebuild the initramfs:

$ sudo dracut --force

Security Notes

The udev rule auto-authorizes Thunderbolt devices only during the brief Dracut window. In the running system, boltd continues to handle authorization normally. In both cases, IOMMU DMA protection remains active, which is the actual security boundary against malicious Thunderbolt devices.

Auto-switch power-profiles-daemon with udev

On GNOME with power-profiles-daemon, I wanted power profiles to flip between power-saver and performance based on AC/battery. The solution is to let udev react to POWER_SUPPLY_ONLINE changes and call powerprofilesctl directly.

Configuration

Put the following rules in /etc/udev/rules.d/99-power-profile-switch.rules:

$ sudo tee /etc/udev/rules.d/99-power-profile-switch.rules >/dev/null <<'EOF'
# AC plugged in
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ENV{POWER_SUPPLY_ONLINE}=="1", ACTION=="change", RUN+="/usr/bin/powerprofilesctl set performance"

# On battery
SUBSYSTEM=="power_supply", ATTR{type}=="Mains", ENV{POWER_SUPPLY_ONLINE}=="0", ACTION=="change", RUN+="/usr/bin/powerprofilesctl set power-saver"
EOF

Reload udev and trigger a change:

$ sudo udevadm control --reload-rules
$ sudo udevadm trigger --subsystem-match=power_supply

Verify

Unplug and replug the AC adapter, then check the active profile:

$ powerprofilesctl get

Changing the webcam’s default power-line frequency

The default powerline frequency for the Logitech C270 webcam is 60Hz, which causes flickering. It can be changed manually via v4l2-ctl or cameractrls, but the change isn’t permanent. To persist the change, we need to create a udev rule. Put the following lines in /etc/udev/rules.d/99-logitech-default-powerline.rules:

# 046d:0825 Logitech, Inc. Webcam C270
SUBSYSTEM=="video4linux", KERNEL=="video[0-9]*", ATTR{index}=="0", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="0825", RUN+="/usr/bin/v4l2-ctl -d $devnode --set-ctrl=power_line_frequency=1"

power_line_frequency value 1 corresponds to 50Hz, 2 to 60Hz and 0 disables the anti-flickering algorithm.