diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md index 10f3ea319340..000df6e978b4 100644 --- a/nixos/doc/manual/release-notes/rl-2411.section.md +++ b/nixos/doc/manual/release-notes/rl-2411.section.md @@ -123,6 +123,8 @@ - [HomeBox](https://github.com/sysadminsmedia/homebox), an inventory and organization system built for the home user. Available as [services.homebox](#opt-services.homebox.enable). +- [evremap](https://github.com/wez/evremap), a keyboard input remapper for Linux/Wayland systems. Available as [services.evremap](options.html#opt-services.evremap). + - [matrix-hookshot](https://matrix-org.github.io/matrix-hookshot), a Matrix bot for connecting to external services. Available as [services.matrix-hookshot](#opt-services.matrix-hookshot.enable). - [Renovate](https://github.com/renovatebot/renovate), a dependency updating tool for various Git forges and language ecosystems. Available as [services.renovate](#opt-services.renovate.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 0537dbf3ad1c..eef106a91229 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -752,6 +752,7 @@ ./services/misc/etebase-server.nix ./services/misc/etesync-dav.nix ./services/misc/evdevremapkeys.nix + ./services/misc/evremap.nix ./services/misc/felix.nix ./services/misc/flaresolverr.nix ./services/misc/forgejo.nix diff --git a/nixos/modules/services/misc/evremap.nix b/nixos/modules/services/misc/evremap.nix new file mode 100644 index 000000000000..9508955d8171 --- /dev/null +++ b/nixos/modules/services/misc/evremap.nix @@ -0,0 +1,167 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.services.evremap; + format = pkgs.formats.toml { }; + + key = lib.types.strMatching "KEY_[[:upper:]]+" // { + description = "key ID prefixed with KEY_"; + }; + + mkKeyOption = + description: + lib.mkOption { + type = key; + description = '' + ${description} + + You can get a list of keys by running `evremap list-keys`. + ''; + }; + mkKeySeqOption = + description: + (mkKeyOption description) + // { + type = lib.types.listOf key; + }; + + dualRoleModule = lib.types.submodule { + options = { + input = mkKeyOption "The key that should be remapped."; + hold = mkKeySeqOption "The key sequence that should be output when the input key is held."; + tap = mkKeySeqOption "The key sequence that should be output when the input key is tapped."; + }; + }; + + remapModule = lib.types.submodule { + options = { + input = mkKeySeqOption "The key sequence that should be remapped."; + output = mkKeySeqOption "The key sequence that should be output when the input sequence is entered."; + }; + }; +in +{ + options.services.evremap = { + enable = lib.mkEnableOption "evremap, a keyboard input remapper for Linux/Wayland systems"; + + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = format.type; + + options = { + device_name = lib.mkOption { + type = lib.types.str; + example = "AT Translated Set 2 keyboard"; + description = '' + The name of the device that should be remapped. + + You can get a list of devices by running `evremap list-devices` with elevated permissions. + ''; + }; + + dual_role = lib.mkOption { + type = lib.types.listOf dualRoleModule; + default = [ ]; + example = [ + { + input = "KEY_CAPSLOCK"; + hold = [ "KEY_LEFTCTRL" ]; + tap = [ "KEY_ESC" ]; + } + ]; + description = '' + List of dual-role remappings that output different key sequences based on whether the + input key is held or tapped. + ''; + }; + + remap = lib.mkOption { + type = lib.types.listOf remapModule; + default = [ ]; + example = [ + { + input = [ + "KEY_LEFTALT" + "KEY_UP" + ]; + output = [ "KEY_PAGEUP" ]; + } + ]; + description = '' + List of remappings. + ''; + }; + }; + }; + + description = '' + Settings for evremap. + + See the [upstream documentation](https://github.com/wez/evremap/blob/master/README.md#configuration) + for how to configure evremap. + ''; + default = { }; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ pkgs.evremap ]; + + hardware.uinput.enable = true; + + systemd.services.evremap = { + description = "evremap - keyboard input remapper"; + wantedBy = [ "multi-user.target" ]; + + script = "${lib.getExe pkgs.evremap} remap ${format.generate "evremap.toml" cfg.settings}"; + + serviceConfig = { + DynamicUser = true; + User = "evremap"; + SupplementaryGroups = [ + config.users.groups.input.name + config.users.groups.uinput.name + ]; + Restart = "on-failure"; + RestartSec = 5; + TimeoutSec = 20; + + # Hardening + ProtectClock = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + ProtectKernelModules = true; + ProtectHostname = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectHome = true; + ProcSubset = "pid"; + + PrivateTmp = true; + PrivateNetwork = true; + PrivateUsers = true; + + RestrictRealtime = true; + RestrictNamespaces = true; + RestrictAddressFamilies = "none"; + + MemoryDenyWriteExecute = true; + LockPersonality = true; + IPAddressDeny = "any"; + AmbientCapabilities = ""; + CapabilityBoundingSet = ""; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@resources" + "~@privileged" + ]; + UMask = "0027"; + }; + }; + }; +} diff --git a/pkgs/by-name/ev/evremap/package.nix b/pkgs/by-name/ev/evremap/package.nix new file mode 100644 index 000000000000..8771aac00093 --- /dev/null +++ b/pkgs/by-name/ev/evremap/package.nix @@ -0,0 +1,36 @@ +{ + lib, + rustPlatform, + fetchFromGitHub, + pkg-config, + libevdev, + nix-update-script, +}: +rustPlatform.buildRustPackage { + pname = "evremap"; + version = "0-unstable-2024-06-17"; + + src = fetchFromGitHub { + owner = "wez"; + repo = "evremap"; + rev = "cc618e8b973f5c6f66682d1477b3b868a768c545"; + hash = "sha256-aAAnlGlSFPOK3h8UuAOlFyrKTEuzbyh613IiPE7xWaA="; + }; + + cargoHash = "sha256-uFej58+51+JX36K1Rr1ZmBe7rHojOjmTO2VWINS6MvU="; + + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ libevdev ]; + + passthru.updateScript = nix-update-script { + extraArgs = [ "--version=branch" ]; + }; + + meta = { + description = "Keyboard input remapper for Linux/Wayland systems"; + homepage = "https://github.com/wez/evremap"; + maintainers = with lib.maintainers; [ pluiedev ]; + license = with lib.licenses; [ mit ]; + mainProgram = "evremap"; + }; +}