mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-10 19:55:41 +03:00

Using `systemd.services.<name>.script` pulls in bash in the ExecStart line for a service. Since our "script" was only one line anyways, we can inline it to just use ExecStart directly. Losing shell features shouldn't be detrimental here, as we're not using pipes and there are no globs to expand.
181 lines
5 KiB
Nix
181 lines
5 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
cfg = config.services.evremap;
|
|
format = pkgs.formats.toml { };
|
|
settings = lib.attrsets.filterAttrs (n: v: v != null) cfg.settings;
|
|
configFile = format.generate "evremap.toml" settings;
|
|
|
|
key = lib.types.strMatching "(BTN|KEY)_[[:upper:][:digit:]_]+" // {
|
|
description = "key ID prefixed with BTN_ or 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.
|
|
'';
|
|
};
|
|
|
|
phys = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "usb-0000:07:00.3-2.1.1/input0";
|
|
description = ''
|
|
The physical device name to listen on.
|
|
|
|
This attribute may be specified to disambiguate multiple devices with the same device name.
|
|
The physical device names of each device can be obtained 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" ];
|
|
|
|
serviceConfig = {
|
|
ExecStart = "${lib.getExe pkgs.evremap} remap ${configFile}";
|
|
|
|
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";
|
|
};
|
|
};
|
|
};
|
|
}
|