mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-11-13 12:13:36 +01:00
* feat(nixpak): pass FIDO2 keys to Firefox, Chromium and Chrome Assisted-by: DeepSeek Harness (deepseek-flash) * feat(nixpak): support FIDO2 hotplug via udev-maintained node directory Replace launch-time hidraw discovery with host udev rules that hard-link FIDO-tagged hidraw nodes into /dev/fido-hidraw and remove them on unplug. The sandbox dev-binds that directory and gets static /dev/hidrawN symlinks into it, so keys plugged in after launch work and no stale node survives a reused hidraw minor. Narrow the extra mounts from whole /sys and /run/udev to /sys/class/hidraw, /run/udev/data and /run/udev/control; the policy suite now forbids the broad mounts and checks the wrapper and bind follow the fido2 option. Assisted-by: Claude Code (claude-opus-5-5) * refactor(nixpak): rewrite FIDO2 bwrap wrapper in Python The bash argument loop was hard to follow. Python inserts the /dev/hidrawN symlinks before "--" with a single list splice, and the header now explains the whole host-udev -> bind -> symlink chain step by step. Assisted-by: Claude Code (claude-opus-5-5) * docs(canokey): document phone-only management policy PCs only use the CanoKey; CanoKey Console management stays in the phone app and the Admin PIN is never typed on a PC. Record what the config enforces (sandboxed browsers get no raw USB/CCID, no vendor WebUSB udev rule) and what it does not (uaccess on the raw USB node, PC/SC access to the Admin applet, CTAP management from browsers). Assisted-by: Claude Code (claude-opus-5-5) * docs(canokey): separate management from use, link CanoKey docs Assisted-by: Claude Code (claude-opus-5-5) * fix(nixpak): create /dev/fido-hidraw from the udev rule NixOS applies /dev tmpfiles entries only at boot; switch-to-configuration runs systemd-tmpfiles-resetup with --exclude-prefix=/dev. After a switch without reboot the directory was missing and every `ln` failed with exit code 1, so no browser saw the key. The add rule now runs `mkdir -p` first. Also fix the documented trigger command: `udevadm trigger` defaults to `change`, which the add-only rule ignores. Assisted-by: Claude Code (claude-opus-5-5) * refactor(nixpak): keep tmpfiles as the only creator of /dev/fido-hidraw The /dev tmpfiles units run before systemd-udevd on every boot, so the directory always exists before coldplug. The mkdir in the udev rule only covered the first switch without reboot and duplicated the tmpfiles rule; drop it and document the one-time `systemd-tmpfiles --prefix` command. Assisted-by: Claude Code (claude-opus-5-5) * docs(nixpak): record FIDO2 hardware validation in Firefox and Chrome After a reboot on ai with the CanoKey present at boot, udev linked only the FIDO interface and WebAuthn works in Firefox and Chrome. Chromium and plugging the key in after launch remain pending. Assisted-by: Claude Code (claude-opus-5-5)
82 lines
2.8 KiB
Nix
82 lines
2.8 KiB
Nix
# Shared browser capabilities. Network topology and application profiles are
|
|
# selected by the app; personal files, browserpass, Secret portal, media and
|
|
# FIDO2 security-key access are explicit opt-ins.
|
|
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
sloth,
|
|
...
|
|
}:
|
|
let
|
|
cfg = config.browserPermissions;
|
|
passwordStore = sloth.concat' sloth.homeDir "/.local/share/password-store";
|
|
# Maintained by the host udev rules in ../default.nix.
|
|
fidoDir = "/dev/fido-hidraw";
|
|
fidoBwrap = import ./fido-bwrap.nix { inherit pkgs fidoDir; };
|
|
in
|
|
{
|
|
imports = [ ./desktop-base.nix ];
|
|
options.browserPermissions = {
|
|
media = lib.mkEnableOption "audio playback/recording, camera and desktop screen sharing";
|
|
personalFiles = lib.mkEnableOption "personal Documents, media directories and Trash";
|
|
browserpass = lib.mkEnableOption "browserpass access to the password store and GPG agent";
|
|
secretPortal = lib.mkEnableOption "the app-scoped Secret portal for v12 cookie encryption";
|
|
fido2 = lib.mkEnableOption "FIDO2 security-key (CanoKey/YubiKey) WebAuthn and passkey access";
|
|
};
|
|
config = {
|
|
portalGroups = {
|
|
fileChooser = true;
|
|
openUri = true;
|
|
notifications = true;
|
|
screenCast = cfg.media;
|
|
camera = cfg.media;
|
|
print = true;
|
|
inhibit = cfg.media;
|
|
inputMethod = true;
|
|
secret = cfg.secretPortal;
|
|
};
|
|
desktopIntegration = {
|
|
notifications = true;
|
|
mpris = cfg.media;
|
|
accessibility = true;
|
|
};
|
|
bubblewrap = {
|
|
package = lib.mkIf cfg.fido2 fidoBwrap;
|
|
sockets.pulse = cfg.media;
|
|
bind.rw = [
|
|
sloth.xdgDownloadDir
|
|
]
|
|
++ lib.optionals cfg.personalFiles [
|
|
sloth.xdgDocumentsDir
|
|
sloth.xdgMusicDir
|
|
sloth.xdgVideosDir
|
|
sloth.xdgPicturesDir
|
|
(sloth.mkdir (sloth.concat' sloth.homeDir "/.local/share/Trash"))
|
|
];
|
|
bind.ro = [
|
|
(sloth.concat' sloth.homeDir "/.config/mimeapps.list")
|
|
(sloth.concat' sloth.homeDir "/.config/user-dirs.dirs")
|
|
(sloth.concat' sloth.homeDir "/.pki/nssdb")
|
|
]
|
|
++ lib.optionals cfg.browserpass [
|
|
"/etc/gnupg"
|
|
(sloth.concat' sloth.homeDir "/.gnupg")
|
|
passwordStore
|
|
(sloth.concat' sloth.runtimeDir "/gnupg")
|
|
]
|
|
# libudev enumeration and hotplug: hidraw class links (device directories
|
|
# come from desktop-base/GPU sysfs binds), the udev database without which
|
|
# devnode-backed devices count as uninitialized, and the control socket
|
|
# whose presence enables the udev monitor. Root owns the socket.
|
|
++ lib.optionals cfg.fido2 [
|
|
"/sys/class/hidraw"
|
|
"/run/udev/data"
|
|
"/run/udev/control"
|
|
];
|
|
bind.dev = lib.optional cfg.fido2 fidoDir;
|
|
env = lib.optionalAttrs cfg.browserpass { PASSWORD_STORE_DIR = passwordStore; };
|
|
};
|
|
};
|
|
}
|