From b6617bb59438cf35177bbd0d612971bf38ac6f67 Mon Sep 17 00:00:00 2001 From: Lin Jian Date: Sun, 24 Jul 2022 23:49:20 +0800 Subject: [PATCH] nixos/kanata: init --- .../from_md/release-notes/rl-2211.section.xml | 8 + .../manual/release-notes/rl-2211.section.md | 4 + nixos/modules/module-list.nix | 1 + nixos/modules/services/hardware/kanata.nix | 156 ++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 + 5 files changed, 171 insertions(+) create mode 100644 nixos/modules/services/hardware/kanata.nix diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml index be3adc4d3be..79f856a4093 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml @@ -133,6 +133,14 @@ services.infnoise. + + + kanata, + a tool to improve keyboard comfort and usability with advanced + customization. Available as + services.kanata. + + persistent-evdev, diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md index 3f9afe13f1d..607da187b89 100644 --- a/nixos/doc/manual/release-notes/rl-2211.section.md +++ b/nixos/doc/manual/release-notes/rl-2211.section.md @@ -58,6 +58,10 @@ In addition to numerous new and upgraded packages, this release has the followin - [infnoise](https://github.com/leetronics/infnoise), a hardware True Random Number Generator dongle. Available as [services.infnoise](options.html#opt-services.infnoise.enable). + +- [kanata](https://github.com/jtroo/kanata), a tool to improve keyboard comfort and usability with advanced customization. + Available as [services.kanata](options.html#opt-services.kanata.enable). + - [persistent-evdev](https://github.com/aiberia/persistent-evdev), a daemon to add virtual proxy devices that mirror a physical input device but persist even if the underlying hardware is hot-plugged. Available as [services.persistent-evdev](#opt-services.persistent-evdev.enable). - [schleuder](https://schleuder.org/), a mailing list manager with PGP support. Enable using [services.schleuder](#opt-services.schleuder.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 3010a213705..d961e2f683b 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -447,6 +447,7 @@ ./services/hardware/interception-tools.nix ./services/hardware/irqbalance.nix ./services/hardware/joycond.nix + ./services/hardware/kanata.nix ./services/hardware/lcd.nix ./services/hardware/lirc.nix ./services/hardware/nvidia-optimus.nix diff --git a/nixos/modules/services/hardware/kanata.nix b/nixos/modules/services/hardware/kanata.nix new file mode 100644 index 00000000000..f8250afa4a0 --- /dev/null +++ b/nixos/modules/services/hardware/kanata.nix @@ -0,0 +1,156 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.kanata; + + keyboard = { + options = { + device = mkOption { + type = types.str; + example = "/dev/input/by-id/usb-0000_0000-event-kbd"; + description = "Path to the keyboard device."; + }; + config = mkOption { + type = types.lines; + example = '' + (defsrc + grv 1 2 3 4 5 6 7 8 9 0 - = bspc + tab q w e r t y u i o p [ ] \ + caps a s d f g h j k l ; ' ret + lsft z x c v b n m , . / rsft + lctl lmet lalt spc ralt rmet rctl) + + (deflayer qwerty + grv 1 2 3 4 5 6 7 8 9 0 - = bspc + tab q w e r t y u i o p [ ] \ + @cap a s d f g h j k l ; ' ret + lsft z x c v b n m , . / rsft + lctl lmet lalt spc ralt rmet rctl) + + (defalias + ;; tap within 100ms for capslk, hold more than 100ms for lctl + cap (tap-hold 100 100 caps lctl)) + ''; + description = '' + Configuration other than defcfg. + See for more information. + ''; + }; + extraDefCfg = mkOption { + type = types.lines; + default = ""; + example = "danger-enable-cmd yes"; + description = '' + Configuration of defcfg other than linux-dev. + See for more information. + ''; + }; + }; + }; + + mkName = name: "kanata-${name}"; + + mkConfig = name: keyboard: pkgs.writeText "${mkName name}-config.kdb" '' + (defcfg + ${keyboard.extraDefCfg} + linux-dev ${keyboard.device}) + + ${keyboard.config} + ''; + + mkService = name: keyboard: nameValuePair (mkName name) { + description = "kanata for ${keyboard.device}"; + + # Because path units are used to activate service units, which + # will start the old stopped services during "nixos-rebuild + # switch", stopIfChanged here is a workaround to make sure new + # services are running after "nixos-rebuild switch". + stopIfChanged = false; + + serviceConfig = { + ExecStart = '' + ${cfg.package}/bin/kanata \ + --cfg ${mkConfig name keyboard} + ''; + + DynamicUser = true; + SupplementaryGroups = with config.users.groups; [ + input.name + uinput.name + ]; + + # hardening + DeviceAllow = [ + "/dev/uinput w" + "char-input r" + ]; + CapabilityBoundingSet = ""; + DevicePolicy = "closed"; + IPAddressDeny = "any"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + PrivateNetwork = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + RestrictAddressFamilies = "none"; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@resources" + ]; + UMask = "0077"; + }; + }; + + mkPath = name: keyboard: nameValuePair (mkName name) { + description = "kanata trigger for ${keyboard.device}"; + wantedBy = [ "multi-user.target" ]; + pathConfig = { + PathExists = keyboard.device; + }; + }; +in +{ + options.services.kanata = { + enable = mkEnableOption "kanata"; + package = mkOption { + type = types.package; + default = pkgs.kanata; + defaultText = lib.literalExpression "pkgs.kanata"; + example = lib.literalExpression "pkgs.kanata-with-cmd"; + description = '' + kanata package to use. + If you enable danger-enable-cmd, pkgs.kanata-with-cmd should be used. + ''; + }; + keyboards = mkOption { + type = types.attrsOf (types.submodule keyboard); + default = { }; + description = "Keyboard configurations."; + }; + }; + + config = lib.mkIf cfg.enable { + hardware.uinput.enable = true; + + systemd = { + paths = mapAttrs' mkPath cfg.keyboards; + services = mapAttrs' mkService cfg.keyboards; + }; + }; + + meta.maintainers = with lib.maintainers; [ linj ]; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 9dab8dd99ab..00d41f48949 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -1231,6 +1231,8 @@ with pkgs; kanata = callPackage ../tools/system/kanata { }; + kanata-with-cmd = callPackage ../tools/system/kanata { withCmd = true; }; + ksnip = libsForQt5.callPackage ../tools/misc/ksnip { }; kubevirt = callPackage ../tools/virtualization/kubevirt { };