nixos/kanata: sync with version 1.0.6
- improve some descriptions - device -> devices - add options - extraArgs - port - create a symlink in RUNTIME_DIRECTORY - grant it read permission of /dev/uinput - relax network-related restrictions when port is used - change type of some hardening options to list to align with systemd - CapabilityBoundingSet - IPAddressDeny - SystemCallArchitectures
This commit is contained in:
parent
a43993655a
commit
b6d45f1448
@ -1,4 +1,4 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, utils, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
@ -7,10 +7,20 @@ let
|
|||||||
|
|
||||||
keyboard = {
|
keyboard = {
|
||||||
options = {
|
options = {
|
||||||
device = mkOption {
|
devices = mkOption {
|
||||||
type = types.str;
|
type = types.addCheck (types.listOf types.str)
|
||||||
example = "/dev/input/by-id/usb-0000_0000-event-kbd";
|
(devices: (length devices) > 0);
|
||||||
description = lib.mdDoc "Path to the keyboard device.";
|
example = [ "/dev/input/by-id/usb-0000_0000-event-kbd" ];
|
||||||
|
# TODO replace note with tip, which has not been implemented yet in
|
||||||
|
# nixos/lib/make-options-doc/mergeJSON.py
|
||||||
|
description = mdDoc ''
|
||||||
|
Paths to keyboard devices.
|
||||||
|
|
||||||
|
::: {.note}
|
||||||
|
To avoid unnecessary triggers of the service unit, unplug devices in
|
||||||
|
the order of the list.
|
||||||
|
:::
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
config = mkOption {
|
config = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
@ -33,18 +43,32 @@ let
|
|||||||
;; tap within 100ms for capslk, hold more than 100ms for lctl
|
;; tap within 100ms for capslk, hold more than 100ms for lctl
|
||||||
cap (tap-hold 100 100 caps lctl))
|
cap (tap-hold 100 100 caps lctl))
|
||||||
'';
|
'';
|
||||||
description = lib.mdDoc ''
|
description = mdDoc ''
|
||||||
Configuration other than defcfg.
|
Configuration other than `defcfg`. See [example config
|
||||||
See <https://github.com/jtroo/kanata> for more information.
|
files](https://github.com/jtroo/kanata) for more information.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
extraDefCfg = mkOption {
|
extraDefCfg = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
default = "";
|
default = "";
|
||||||
example = "danger-enable-cmd yes";
|
example = "danger-enable-cmd yes";
|
||||||
description = lib.mdDoc ''
|
description = mdDoc ''
|
||||||
Configuration of defcfg other than linux-dev.
|
Configuration of `defcfg` other than `linux-dev`. See [example
|
||||||
See <https://github.com/jtroo/kanata> for more information.
|
config files](https://github.com/jtroo/kanata) for more information.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
extraArgs = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = mdDoc "Extra command line arguments passed to kanata.";
|
||||||
|
};
|
||||||
|
port = mkOption {
|
||||||
|
type = types.nullOr types.port;
|
||||||
|
default = null;
|
||||||
|
example = 6666;
|
||||||
|
description = mdDoc ''
|
||||||
|
Port to run the notification server on. `null` will not run the
|
||||||
|
server.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -52,16 +76,18 @@ let
|
|||||||
|
|
||||||
mkName = name: "kanata-${name}";
|
mkName = name: "kanata-${name}";
|
||||||
|
|
||||||
|
mkDevices = devices: concatStringsSep ":" devices;
|
||||||
|
|
||||||
mkConfig = name: keyboard: pkgs.writeText "${mkName name}-config.kdb" ''
|
mkConfig = name: keyboard: pkgs.writeText "${mkName name}-config.kdb" ''
|
||||||
(defcfg
|
(defcfg
|
||||||
${keyboard.extraDefCfg}
|
${keyboard.extraDefCfg}
|
||||||
linux-dev ${keyboard.device})
|
linux-dev ${mkDevices keyboard.devices})
|
||||||
|
|
||||||
${keyboard.config}
|
${keyboard.config}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
mkService = name: keyboard: nameValuePair (mkName name) {
|
mkService = name: keyboard: nameValuePair (mkName name) {
|
||||||
description = "kanata for ${keyboard.device}";
|
description = "kanata for ${mkDevices keyboard.devices}";
|
||||||
|
|
||||||
# Because path units are used to activate service units, which
|
# Because path units are used to activate service units, which
|
||||||
# will start the old stopped services during "nixos-rebuild
|
# will start the old stopped services during "nixos-rebuild
|
||||||
@ -72,10 +98,14 @@ let
|
|||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${cfg.package}/bin/kanata \
|
${cfg.package}/bin/kanata \
|
||||||
--cfg ${mkConfig name keyboard}
|
--cfg ${mkConfig name keyboard} \
|
||||||
|
--symlink-path ''${RUNTIME_DIRECTORY}/${name} \
|
||||||
|
${optionalString (keyboard.port != null) "--port ${toString keyboard.port}"} \
|
||||||
|
${utils.escapeSystemdExecArgs keyboard.extraArgs}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
DynamicUser = true;
|
DynamicUser = true;
|
||||||
|
RuntimeDirectory = mkName name;
|
||||||
SupplementaryGroups = with config.users.groups; [
|
SupplementaryGroups = with config.users.groups; [
|
||||||
input.name
|
input.name
|
||||||
uinput.name
|
uinput.name
|
||||||
@ -83,15 +113,16 @@ let
|
|||||||
|
|
||||||
# hardening
|
# hardening
|
||||||
DeviceAllow = [
|
DeviceAllow = [
|
||||||
"/dev/uinput w"
|
"/dev/uinput rw"
|
||||||
"char-input r"
|
"char-input r"
|
||||||
];
|
];
|
||||||
CapabilityBoundingSet = "";
|
CapabilityBoundingSet = [ "" ];
|
||||||
DevicePolicy = "closed";
|
DevicePolicy = "closed";
|
||||||
IPAddressDeny = "any";
|
IPAddressAllow = optional (keyboard.port != null) "localhost";
|
||||||
|
IPAddressDeny = [ "any" ];
|
||||||
LockPersonality = true;
|
LockPersonality = true;
|
||||||
MemoryDenyWriteExecute = true;
|
MemoryDenyWriteExecute = true;
|
||||||
PrivateNetwork = true;
|
PrivateNetwork = keyboard.port == null;
|
||||||
PrivateUsers = true;
|
PrivateUsers = true;
|
||||||
ProcSubset = "pid";
|
ProcSubset = "pid";
|
||||||
ProtectClock = true;
|
ProtectClock = true;
|
||||||
@ -102,10 +133,11 @@ let
|
|||||||
ProtectKernelModules = true;
|
ProtectKernelModules = true;
|
||||||
ProtectKernelTunables = true;
|
ProtectKernelTunables = true;
|
||||||
ProtectProc = "invisible";
|
ProtectProc = "invisible";
|
||||||
RestrictAddressFamilies = "none";
|
RestrictAddressFamilies =
|
||||||
|
if (keyboard.port == null) then "none" else [ "AF_INET" ];
|
||||||
RestrictNamespaces = true;
|
RestrictNamespaces = true;
|
||||||
RestrictRealtime = true;
|
RestrictRealtime = true;
|
||||||
SystemCallArchitectures = "native";
|
SystemCallArchitectures = [ "native" ];
|
||||||
SystemCallFilter = [
|
SystemCallFilter = [
|
||||||
"@system-service"
|
"@system-service"
|
||||||
"~@privileged"
|
"~@privileged"
|
||||||
@ -115,13 +147,32 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
mkPath = name: keyboard: nameValuePair (mkName name) {
|
mkPathName = i: name: "${mkName name}-${toString i}";
|
||||||
description = "kanata trigger for ${keyboard.device}";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
mkPath = name: n: i: device:
|
||||||
pathConfig = {
|
nameValuePair (mkPathName i name) {
|
||||||
PathExists = keyboard.device;
|
description =
|
||||||
|
"${toString (i+1)}/${toString n} kanata trigger for ${name}, watching ${device}";
|
||||||
|
wantedBy = optional (i == 0) "multi-user.target";
|
||||||
|
pathConfig = {
|
||||||
|
PathExists = device;
|
||||||
|
# (ab)use systemd.path to construct a trigger chain so that the
|
||||||
|
# service unit is only started when all paths exist
|
||||||
|
# however, manual of systemd.path says Unit's suffix is not ".path"
|
||||||
|
Unit =
|
||||||
|
if (i + 1) == n
|
||||||
|
then "${mkName name}.service"
|
||||||
|
else "${mkPathName (i + 1) name}.path";
|
||||||
|
};
|
||||||
|
unitConfig.StopPropagatedFrom = optional (i > 0) "${mkName name}.service";
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
mkPaths = name: keyboard:
|
||||||
|
let
|
||||||
|
n = length keyboard.devices;
|
||||||
|
in
|
||||||
|
imap0 (mkPath name n) keyboard.devices
|
||||||
|
;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.kanata = {
|
options.services.kanata = {
|
||||||
@ -131,15 +182,19 @@ in
|
|||||||
default = pkgs.kanata;
|
default = pkgs.kanata;
|
||||||
defaultText = lib.literalExpression "pkgs.kanata";
|
defaultText = lib.literalExpression "pkgs.kanata";
|
||||||
example = lib.literalExpression "pkgs.kanata-with-cmd";
|
example = lib.literalExpression "pkgs.kanata-with-cmd";
|
||||||
description = lib.mdDoc ''
|
description = mdDoc ''
|
||||||
kanata package to use.
|
The kanata package to use.
|
||||||
If you enable danger-enable-cmd, pkgs.kanata-with-cmd should be used.
|
|
||||||
|
::: {.note}
|
||||||
|
If `danger-enable-cmd` is enabled in any of the keyboards, the
|
||||||
|
`kanata-with-cmd` package should be used.
|
||||||
|
:::
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
keyboards = mkOption {
|
keyboards = mkOption {
|
||||||
type = types.attrsOf (types.submodule keyboard);
|
type = types.attrsOf (types.submodule keyboard);
|
||||||
default = { };
|
default = { };
|
||||||
description = lib.mdDoc "Keyboard configurations.";
|
description = mdDoc "Keyboard configurations.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,7 +202,11 @@ in
|
|||||||
hardware.uinput.enable = true;
|
hardware.uinput.enable = true;
|
||||||
|
|
||||||
systemd = {
|
systemd = {
|
||||||
paths = mapAttrs' mkPath cfg.keyboards;
|
paths = trivial.pipe cfg.keyboards [
|
||||||
|
(mapAttrsToList mkPaths)
|
||||||
|
concatLists
|
||||||
|
listToAttrs
|
||||||
|
];
|
||||||
services = mapAttrs' mkService cfg.keyboards;
|
services = mapAttrs' mkService cfg.keyboards;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user