grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / hardware / keyd.nix
blob92b62fe2e9775e0ddfdc0836203e82ccae2d4e6e
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.keyd;
5   keyboardOptions = { ... }: {
6     options = {
7       ids = lib.mkOption {
8         type = lib.types.listOf lib.types.str;
9         default = [ "*" ];
10         example = [ "*" "-0123:0456" ];
11         description = ''
12           Device identifiers, as shown by {manpage}`keyd(1)`.
13         '';
14       };
16       settings = lib.mkOption {
17         type = (pkgs.formats.ini { }).type;
18         default = { };
19         example = {
20           main = {
21             capslock = "overload(control, esc)";
22             rightalt = "layer(rightalt)";
23           };
25           rightalt = {
26             j = "down";
27             k = "up";
28             h = "left";
29             l = "right";
30           };
31         };
32         description = ''
33           Configuration, except `ids` section, that is written to {file}`/etc/keyd/<keyboard>.conf`.
34           Appropriate names can be used to write non-alpha keys, for example "equal" instead of "=" sign (see <https://github.com/NixOS/nixpkgs/issues/236622>).
35           See <https://github.com/rvaiya/keyd> how to configure.
36         '';
37       };
39       extraConfig = lib.mkOption {
40         type = lib.types.lines;
41         default = "";
42         example = ''
43           [control+shift]
44           h = left
45         '';
46         description = ''
47           Extra configuration that is appended to the end of the file.
48           **Do not** write `ids` section here, use a separate option for it.
49           You can use this option to define compound layers that must always be defined after the layer they are comprised.
50         '';
51       };
52     };
53   };
56   imports = [
57     (lib.mkRemovedOptionModule [ "services" "keyd" "ids" ]
58       ''Use keyboards.<filename>.ids instead. If you don't need a multi-file configuration, just add keyboards.default before the ids. See https://github.com/NixOS/nixpkgs/pull/243271.'')
59     (lib.mkRemovedOptionModule [ "services" "keyd" "settings" ]
60       ''Use keyboards.<filename>.settings instead. If you don't need a multi-file configuration, just add keyboards.default before the settings. See https://github.com/NixOS/nixpkgs/pull/243271.'')
61   ];
63   options.services.keyd = {
64     enable = lib.mkEnableOption "keyd, a key remapping daemon";
66     keyboards = lib.mkOption {
67       type = lib.types.attrsOf (lib.types.submodule keyboardOptions);
68       default = { };
69       example = lib.literalExpression ''
70         {
71           default = {
72             ids = [ "*" ];
73             settings = {
74               main = {
75                 capslock = "overload(control, esc)";
76               };
77             };
78           };
79           externalKeyboard = {
80             ids = [ "1ea7:0907" ];
81             settings = {
82               main = {
83                 esc = capslock;
84               };
85             };
86           };
87         }
88       '';
89       description = ''
90         Configuration for one or more device IDs. Corresponding files in the /etc/keyd/ directory are created according to the name of the keys (like `default` or `externalKeyboard`).
91       '';
92     };
93   };
95   config = lib.mkIf cfg.enable {
96     # Creates separate files in the `/etc/keyd/` directory for each key in the dictionary
97     environment.etc = lib.mapAttrs'
98       (name: options:
99         lib.nameValuePair "keyd/${name}.conf" {
100           text = ''
101             [ids]
102             ${lib.concatStringsSep "\n" options.ids}
104             ${lib.generators.toINI {} options.settings}
105             ${options.extraConfig}
106           '';
107         })
108       cfg.keyboards;
110     hardware.uinput.enable = lib.mkDefault true;
112     systemd.services.keyd = {
113       description = "Keyd remapping daemon";
114       documentation = [ "man:keyd(1)" ];
116       wantedBy = [ "multi-user.target" ];
118       restartTriggers = lib.mapAttrsToList
119         (name: options:
120           config.environment.etc."keyd/${name}.conf".source
121         )
122         cfg.keyboards;
124       # this is configurable in 2.4.2, later versions seem to remove this option.
125       # post-2.4.2 may need to set makeFlags in the derivation:
126       #
127       #     makeFlags = [ "SOCKET_PATH/run/keyd/keyd.socket" ];
128       environment.KEYD_SOCKET = "/run/keyd/keyd.sock";
130       serviceConfig = {
131         ExecStart = "${pkgs.keyd}/bin/keyd";
132         Restart = "always";
134         # TODO investigate why it doesn't work propeprly with DynamicUser
135         # See issue: https://github.com/NixOS/nixpkgs/issues/226346
136         # DynamicUser = true;
137         SupplementaryGroups = [
138           config.users.groups.input.name
139           config.users.groups.uinput.name
140         ];
142         RuntimeDirectory = "keyd";
144         # Hardening
145         CapabilityBoundingSet = [ "CAP_SYS_NICE" ];
146         DeviceAllow = [
147           "char-input rw"
148           "/dev/uinput rw"
149         ];
150         ProtectClock = true;
151         PrivateNetwork = true;
152         ProtectHome = true;
153         ProtectHostname = true;
154         PrivateUsers = false;
155         PrivateMounts = true;
156         PrivateTmp = true;
157         RestrictNamespaces = true;
158         ProtectKernelLogs = true;
159         ProtectKernelModules = true;
160         ProtectKernelTunables = true;
161         ProtectControlGroups = true;
162         MemoryDenyWriteExecute = true;
163         RestrictRealtime = true;
164         LockPersonality = true;
165         ProtectProc = "invisible";
166         SystemCallFilter = [
167           "nice"
168           "@system-service"
169           "~@privileged"
170         ];
171         RestrictAddressFamilies = [ "AF_UNIX" ];
172         RestrictSUIDSGID = true;
173         IPAddressDeny = [ "any" ];
174         NoNewPrivileges = true;
175         ProtectSystem = "strict";
176         ProcSubset = "pid";
177         UMask = "0077";
178       };
179     };
180   };