Skip to content
FreeBSDHow-To Published Updated 3 min readViews unavailable

How to Automate FreeBSD Device Events Safely with devd Rules

How to observe devd events, match stable properties, call a constrained helper, control concurrency, test detach paths, and preserve boot reliability.

devd(8) listens for kernel device-state events and applies rules from devd.conf and local configuration directories. It can react to attach/detach, link changes, ACPI notifications, USB devices, and other system events. Because it runs as a privileged daemon and receives hardware-controlled data, its rules should dispatch narrow, audited helpers—not interpolate event strings into an all-purpose shell.

Observe the real event first

Do not guess property names from another device. Run the documented foreground/debug mode on a console-accessible test host, attach and detach the device, and capture the event fields. Also inspect normal system state:

service devd status
devctl monitor
usbconfig list

devctl monitor and devd debugging expose related event streams, but the exact fields available to a devd rule depend on event system and release. Record vendor/product IDs, subsystem, device name, action, serial when available, and which properties remain stable across ports and reboot.

Put local policy outside the base file

Keep local rules under /usr/local/etc/devd/ with a descriptive .conf name so operating-system updates do not overwrite them. A conceptual notify rule looks like this:

notify 100 {
    match "system" "USB";
    match "subsystem" "DEVICE";
    match "type" "ATTACH";
    match "vendor" "0x1234";
    match "product" "0xabcd";
    action "/usr/local/libexec/site-usb-handler attach";
};

Property names and values above are illustrative. Use those observed on the target and validate against devd.conf(5). Match as narrowly as the use case permits; a vendor ID alone can authorize every product from that vendor.

Make the helper the security boundary

Use an absolute path to a root-owned, non-writable executable. Pass a fixed action plus the minimum validated event properties. Inside the helper:

  • set a known PATH or use absolute commands;
  • reject values outside a strict allowlist;
  • quote every expansion;
  • use a lock to serialize conflicting events;
  • apply timeouts to external operations;
  • log a stable event ID and result;
  • make repeated attach or detach idempotent.

Do not embed a long shell pipeline in action. Event bursts, names containing metacharacters, and partial failure are much easier to handle in a tested program.

Priority and rule type affect execution

devd rules have priorities, and notify, attach, detach, and nomatch forms serve different event paths. Multiple matching notify rules can run, while attach/detach selection has its own documented behavior. Choose a site priority intentionally and inspect existing base and package rules to avoid contradictory actions.

Hardware arrival can occur before filesystems, networking, or a package service is ready during boot. If the action needs another service, enqueue work or notify an rc.d-managed daemon rather than blocking devd on a fragile network request.

Validate configuration before reload

Use devd’s supported configuration-check/debug invocation for the installed release, then reload in a maintenance window. Keep the existing daemon running until syntax is proven. Watch /var/log and the console for parse errors.

Test attach, repeated attach, detach during work, rapid flap, boot with device present, boot without it, wrong vendor/product, helper timeout, helper crash, and daemon restart. Verify that no event can mount an unexpected filesystem, replace a trusted path, or run uncontrolled device content.

Prefer stable identifiers, but expect absence

USB serial numbers can distinguish units, yet some devices omit or clone them. Kernel device names can change with enumeration. Build rules around the strongest available combination and require an application-level identity check before destructive or privileged work.

For storage, never format, decrypt, or mount read-write solely because a USB ID matched. Inspect GEOM labels, filesystem UUID, encryption metadata, expected size, and mount target, with nosuid/noexec/read-only policy where appropriate.

devd is best used as a small event router. The durable automation belongs in a separately testable helper with explicit identity, concurrency, and rollback behavior.

Related:

Sources:

Comments