Am I doing something wrong with this kanata config?

I’m trying:

  services.kanata = {
    enable = true;
    keyboards = {
      kanata.extraDefCfg = "process-unmapped-keys yes";
      kanata.config = ''
        (defsrc)
        (defvar)
        (defalias)
        (deflayer base)
      '';
    };
  };

When I run this, I get this [ERROR] Failed to open the output uinput device. Make sure you've added the user executing kanata to the uinput group when trying to start the kanata service.

Error output
warning: the following units failed: kanata-kanata.service
× kanata-kanata.service
     Loaded: loaded (/etc/systemd/system/kanata-kanata.service; enabled; preset: ignored)
     Active: failed (Result: exit-code) since Sat 2025-08-02 22:04:24 CEST; 372ms ago
 Invocation: 2e367dd008c24362bbfc8708d682f511
    Process: 4070577 ExecStart=/nix/store/dj6k1gkmrjvrmj1dqqr83g81vblwsid7-kanata-1.8.1/bin/kanata --cfg /nix/store/3bvl3zx41wbviy9sb4h4h0ksfapm6xsy-kanata-kanata-config.kdb --symlink-path ${RUNTIME_DIRECTORY}/kanata (code=exited, status=1/FAILURE)
   Main PID: 4070577 (code=exited, status=1/FAILURE)
         IP: 0B in, 0B out
         IO: 0B read, 0B written
   Mem peak: 2.4M
        CPU: 51ms

Aug 02 22:04:24 kosh kanata[4070577]: 22:04:24.1037 [INFO] process unmapped keys: true
Aug 02 22:04:24 kosh kanata[4070577]: 22:04:24.1037 [INFO] NOTE: kanata was compiled to never allow cmd
Aug 02 22:04:24 kosh kanata[4070577]: 22:04:24.1038 [INFO] config file is valid
Aug 02 22:04:24 kosh kanata[4070577]: 22:04:24.1038 [ERROR] Failed to open the output uinput device. Make sure you've added the user executing kanata to the `uinput` group
Aug 02 22:04:24 kosh kanata[4070577]: 22:04:24.1038 [ERROR] Permission denied (os error 13)
Aug 02 22:04:24 kosh kanata[4070577]: Press enter to exit
Aug 02 22:04:24 kosh kanata[4070577]: Error: Permission denied (os error 13)
Aug 02 22:04:24 kosh systemd[1]: kanata-kanata.service: Main process exited, code=exited, status=1/FAILURE
Aug 02 22:04:24 kosh systemd[1]: kanata-kanata.service: Failed with result 'exit-code'.
Aug 02 22:04:24 kosh systemd[1]: Failed to start kanata-kanata.service.

Where /etc/systemd/system/kanata-kanata.service contains both DynamicUser and SupplementaryGroups setting adding the user to th uinput group, but it doesn’t look like they work together.

Contents of /etc/systemd/system/kanata-kanata.service
[Unit]

[Service]
Environment="LOCALE_ARCHIVE=/nix/store/0ip389clsbrbjmhmrysgfghqnhx8qlfd-glibc-locales-2.40-66/lib/locale/locale-archive"
Environment="PATH=/nix/store/87fck6hm17chxjq7badb11mq036zbyv9-coreutils-9.7/bin:/nix/store/7y59hzi3svdj1xjddjn2k7km96pifcyl-findutils-4.10.0/bin:/nix/store/gqmr3gixlddz3667ba1iyqck3c0dkpvd-gnugrep-3.11/bin:/nix/store/clbb2cvigynr235ab5zgi18dyavznlk2-gnused-4.9/bin:/nix/store/if9z6wmzmb07j63c02mvfkhn1mw1w5p4-systemd-257.5/bin:/nix/store/87fck6hm17chxjq7badb11mq036zbyv9-coreutils-9.7/sbin:/nix/store/7y59hzi3svdj1xjddjn2k7km96pifcyl-findutils-4.10.0/sbin:/nix/store/gqmr3gixlddz3667ba1iyqck3c0dkpvd-gnugrep-3.11/sbin:/nix/store/clbb2cvigynr235ab5zgi18dyavznlk2-gnused-4.9/sbin:/nix/store/if9z6wmzmb07j63c02mvfkhn1mw1w5p4-systemd-257.5/sbin"
Environment="TZDIR=/nix/store/qyihkwbhd70ynz380whj3bsxk1d2lyc4-tzdata-2025b/share/zoneinfo"
CapabilityBoundingSet=
DeviceAllow=/dev/uinput rw
DeviceAllow=char-input r
DevicePolicy=closed
DynamicUser=true
ExecStart=/nix/store/dj6k1gkmrjvrmj1dqqr83g81vblwsid7-kanata-1.8.1/bin/kanata \
  --cfg /nix/store/3bvl3zx41wbviy9sb4h4h0ksfapm6xsy-kanata-kanata-config.kdb \
  --symlink-path ${RUNTIME_DIRECTORY}/kanata \
   \
  

IPAddressDeny=any
LockPersonality=true
MemoryDenyWriteExecute=true
PrivateNetwork=true
PrivateUsers=true
ProcSubset=pid
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=invisible
RestrictAddressFamilies=AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
RuntimeDirectory=kanata-kanata
SupplementaryGroups=input
SupplementaryGroups=uinput
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged
SystemCallFilter=~@resources
Type=notify
UMask=0077

[Install]
WantedBy=multi-user.target

Starting from something that works

This works:

  ## users.groups.input = {};
  ## users.groups.uinput = {};
  systemd.services.kanata = {
    description = "Kanata Service";
    requires = [ "local-fs.target" ];
    after = [ "local-fs.target" ];
    wantedBy = [ "sysinit.target" ];

    serviceConfig = {
      ExecStartPre = "${pkgs.kmod}/bin/modprobe uinput";
      ExecStart = "${pkgs.kanata}/bin/kanata -c /kanata.kbd";
      # ExecStart = "${pkgs.kanata}/bin/kanata -c /home/peter/.config/kanata/peter.kbd";
      Restart = "on-failure";
      # If I do this, the systemd service doesn't fail, but it also doesn't work:
      ## DynamicUser = true;
      ## SupplementaryGroups = [
      ##   "input"
      ##   "uinput"
      ## ];
    };
  };

The service starts fine and Kanata runs like I want (with some lines commented out like above).

If I uncomment the lines with ## above, I see a similar error behavior to the failing services.kanata above:

$ sudo nixos-rebuild test
warning: Git tree '/etc/nixos' is dirty
building the system configuration...
warning: Git tree '/etc/nixos' is dirty
activating the configuration...
sops-install-secrets: Imported /etc/ssh/ssh_host_rsa_key as GPG key with fingerprint 3f25eb937209c085c11b4ad9733a306988e5a178
sops-install-secrets: Imported /etc/ssh/ssh_host_ed25519_key as age key with fingerprint age1gdswf8t0ge6smrwcm83ndfhg6qdnfkxm56exf8tf25l00053te7qu8m0ee
setting up /etc...
sops-install-secrets: Imported /etc/ssh/ssh_host_rsa_key as GPG key with fingerprint 3f25eb937209c085c11b4ad9733a306988e5a178
sops-install-secrets: Imported /etc/ssh/ssh_host_ed25519_key as age key with fingerprint age1gdswf8t0ge6smrwcm83ndfhg6qdnfkxm56exf8tf25l00053te7qu8m0ee
reloading user units for peter...
restarting sysinit-reactivation.target
warning: the following units failed: kanata.service
● kanata.service - Kanata Service
     Loaded: loaded (/etc/systemd/system/kanata.service; enabled; preset: ignored)
     Active: activating (auto-restart) (Result: exit-code) since Sat 2025-08-02 21:49:38 CEST; 23ms ago
 Invocation: 4aea0d0034ff4e5b8bfdef86d1c2771a
    Process: 4034322 ExecStartPre=/nix/store/qvyvscqgr6vyqvmjdgxqa521myv5db0p-kmod-31/bin/modprobe uinput (code=exited, status=0/SUCCESS)
    Process: 4034323 ExecStart=/nix/store/dj6k1gkmrjvrmj1dqqr83g81vblwsid7-kanata-1.8.1/bin/kanata -c /kanata.kbd (code=exited, status=1/FAILURE)
   Main PID: 4034323 (code=exited, status=1/FAILURE)
         IP: 0B in, 0B out
         IO: 0B read, 0B written
   Mem peak: 1.9M
        CPU: 32ms
warning: error(s) occurred while switching to the new configuration

$ journalctl --invocation=4aea0d0034ff4e5b8bfdef86d1c2771a | cat
Aug 02 21:49:38 kosh systemd[1]: Starting Kanata Service...
Aug 02 21:49:38 kosh systemd[1]: Started Kanata Service.
Aug 02 21:49:38 kosh kanata[4034323]: 21:49:38.4762 [INFO] kanata v1.8.1 starting
Aug 02 21:49:38 kosh kanata[4034323]: 21:49:38.4763 [INFO] process unmapped keys: true
Aug 02 21:49:38 kosh kanata[4034323]: 21:49:38.4764 [INFO] NOTE: kanata was compiled to never allow cmd
Aug 02 21:49:38 kosh kanata[4034323]: 21:49:38.4765 [INFO] config file is valid
Aug 02 21:49:38 kosh kanata[4034323]: 21:49:38.4765 [ERROR] Failed to open the output uinput device. Make sure you've added the user executing kanata to the `uinput` group
Aug 02 21:49:38 kosh kanata[4034323]: 21:49:38.4765 [ERROR] Permission denied (os error 13)
Aug 02 21:49:38 kosh kanata[4034323]: Press enter to exit
Aug 02 21:49:38 kosh kanata[4034323]: Error: Permission denied (os error 13)
Aug 02 21:49:38 kosh systemd[1]: kanata.service: Main process exited, code=exited, status=1/FAILURE
Aug 02 21:49:38 kosh systemd[1]: kanata.service: Failed with result 'exit-code'.
Aug 02 21:49:38 kosh systemd[1]: kanata.service: Scheduled restart job, restart counter is at 2.

Because of this experiment, it looks to me like DynamicUser and SupplementaryGroups not working together is the cause of it not working, but I assume the kanata service works for at least some people, since that is what kanata.nix creates.

There was this related but inconclusive thread about DynamicUser and SupplementaryGroups: How to add the Kanata service, which runs as a systemd dynamic user, to a group? - Help - NixOS Discourse

Am I doing something wrong? Can I get the stock kanata service to work?

Or should I just file a bug here: https://github.com/NixOS/nixpkgs/issues?