at 23.11-pre 3.5 kB view raw
1{ config, lib, pkgs, ... }: 2with lib; 3let 4 cfg = config.services.keyd; 5 settingsFormat = pkgs.formats.ini { }; 6in 7{ 8 options = { 9 services.keyd = { 10 enable = mkEnableOption (lib.mdDoc "keyd, a key remapping daemon"); 11 12 ids = mkOption { 13 type = types.listOf types.string; 14 default = [ "*" ]; 15 example = [ "*" "-0123:0456" ]; 16 description = lib.mdDoc '' 17 Device identifiers, as shown by {manpage}`keyd(1)`. 18 ''; 19 }; 20 21 settings = mkOption { 22 type = settingsFormat.type; 23 default = { }; 24 example = { 25 main = { 26 capslock = "overload(control, esc)"; 27 rightalt = "layer(rightalt)"; 28 }; 29 30 rightalt = { 31 j = "down"; 32 k = "up"; 33 h = "left"; 34 l = "right"; 35 }; 36 }; 37 description = lib.mdDoc '' 38 Configuration, except `ids` section, that is written to {file}`/etc/keyd/default.conf`. 39 See <https://github.com/rvaiya/keyd> how to configure. 40 ''; 41 }; 42 }; 43 }; 44 45 config = mkIf cfg.enable { 46 environment.etc."keyd/default.conf".source = pkgs.runCommand "default.conf" 47 { 48 ids = '' 49 [ids] 50 ${concatStringsSep "\n" cfg.ids} 51 ''; 52 passAsFile = [ "ids" ]; 53 } '' 54 cat $idsPath <(echo) ${settingsFormat.generate "keyd-main.conf" cfg.settings} >$out 55 ''; 56 57 hardware.uinput.enable = lib.mkDefault true; 58 59 systemd.services.keyd = { 60 description = "Keyd remapping daemon"; 61 documentation = [ "man:keyd(1)" ]; 62 63 wantedBy = [ "multi-user.target" ]; 64 65 restartTriggers = [ 66 config.environment.etc."keyd/default.conf".source 67 ]; 68 69 # this is configurable in 2.4.2, later versions seem to remove this option. 70 # post-2.4.2 may need to set makeFlags in the derivation: 71 # 72 # makeFlags = [ "SOCKET_PATH/run/keyd/keyd.socket" ]; 73 environment.KEYD_SOCKET = "/run/keyd/keyd.sock"; 74 75 serviceConfig = { 76 ExecStart = "${pkgs.keyd}/bin/keyd"; 77 Restart = "always"; 78 79 # TODO investigate why it doesn't work propeprly with DynamicUser 80 # See issue: https://github.com/NixOS/nixpkgs/issues/226346 81 # DynamicUser = true; 82 SupplementaryGroups = [ 83 config.users.groups.input.name 84 config.users.groups.uinput.name 85 ]; 86 87 RuntimeDirectory = "keyd"; 88 89 # Hardening 90 CapabilityBoundingSet = ""; 91 DeviceAllow = [ 92 "char-input rw" 93 "/dev/uinput rw" 94 ]; 95 ProtectClock = true; 96 PrivateNetwork = true; 97 ProtectHome = true; 98 ProtectHostname = true; 99 PrivateUsers = true; 100 PrivateMounts = true; 101 PrivateTmp = true; 102 RestrictNamespaces = true; 103 ProtectKernelLogs = true; 104 ProtectKernelModules = true; 105 ProtectKernelTunables = true; 106 ProtectControlGroups = true; 107 MemoryDenyWriteExecute = true; 108 RestrictRealtime = true; 109 LockPersonality = true; 110 ProtectProc = "invisible"; 111 SystemCallFilter = [ 112 "@system-service" 113 "~@privileged" 114 "~@resources" 115 ]; 116 RestrictAddressFamilies = [ "AF_UNIX" ]; 117 RestrictSUIDSGID = true; 118 IPAddressDeny = [ "any" ]; 119 NoNewPrivileges = true; 120 ProtectSystem = "strict"; 121 ProcSubset = "pid"; 122 UMask = "0077"; 123 }; 124 }; 125 }; 126}