Cannot get keyd working on 25.11

I cannot get keyd working despite following the NixOS guide. I’m 2 days into NixOS and pulling my hair out over this. I’ve sunk maybe 8 hours into it.

Here is my configuration.nix.

# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];

  # Bootloader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  networking.hostName = <REMOVED>; # Define your hostname.
  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.

  # Configure network proxy if necessary
  # networking.proxy.default = "http://user:password@proxy:port/";
  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";

  # Enable networking
  networking.networkmanager.enable = true;

  # Set your time zone.
  time.timeZone = <REMOVED>;

  # Select internationalisation properties.
  i18n.defaultLocale = <REMOVED>;

  i18n.extraLocaleSettings = <REMOVED>;

  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "us";
    variant = "";
  };

  # Ly
  services.displayManager.ly = {
    enable = true;
    settings = {
      shutdown_key = "F1";
      restart_key = "F2";
      brightness_down_key = "F3";
      brightness_up_key = "F4";
      hide_version_string = true;
    };
  };

  # Fish
  programs.fish.enable = true;

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.<REMOVED> = {
    isNormalUser = true;
    description = <REMOVED>;
    extraGroups = [ "networkmanager" "wheel" ];
    packages = with pkgs; [];
    shell = pkgs.fish;
  };

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
    alacritty
    copyq
    element-desktop
    fastfetch
    firefox
    fish
    fuzzel
    git
    keyd
    neovim
    niri
    nodejs
    python314
    rofi
    swaylock
    texliveFull
    tree
    vsce
    vscodium
    waybar
    wget
    yazi
  ];

  # XDG portal
  xdg.portal.enable = true;

  # Niri
  programs.niri.enable = true;
 
  # Keyd
  services.keyd = {
    enable = true;  
    keyboards.default = {
      ids = [ "*" ];
      # Maps capslock to escape when pressed and control when held.
      settings.main.capslock = "overload(meta, esc)";
      # Remaps the escape key to capslock
      settings.main.esc = "capslock";
      # Disables the left meta key
      settings.main.leftmeta = "noop"; 
    };
  };

  # Waybar
  # programs.waybar.enable = true;

  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  # services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  # networking.firewall.enable = false;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "25.11"; # Did you read the comment?

}

When I build the system I get the following warning.

warning: the following units failed: keyd.service
● keyd.service - Keyd remapping daemon
     Loaded: loaded (/etc/systemd/system/keyd.service; enabled; preset: ignored)
     Active: activating (auto-restart) (Result: exit-code) since Wed 2026-02-25 12:47:53 CET; 64ms ago
 Invocation: b8e95ae2f5ab42cd888d8a5482c08c4d
       Docs: man:keyd(1)
    Process: 40919 ExecStart=/nix/store/apzpq5i83y8knkjliqhkah52awd8776m-keyd-2.5.0/bin/keyd (code=exited, status=255/EXCEPTION)
   Main PID: 40919 (code=exited, status=255/EXCEPTION)
         IP: 0B in, 0B out
         IO: 0B read, 0B written
   Mem peak: 3M
        CPU: 33ms
Command 'systemd-run -E LOCALE_ARCHIVE -E NIXOS_INSTALL_BOOTLOADER --collect --no-ask-password --pipe --quiet --service-type=exec --unit=nixos-rebuild-switch-to-configuration /nix/store/x651my3zvca1gjydnvbyfa44pbdfi4zw-nixos-system-<REMOVED>-eb630-25.11.6220.6d41bc27aaf7/bin/switch-to-configuration switch' returned non-zero exit status 4.

Here is the status of the service.

$ sudo systemctl status keyd
× keyd.service - Keyd remapping daemon
     Loaded: loaded (/etc/systemd/system/keyd.service; enabled; preset: ignored)
     Active: failed (Result: exit-code) since Wed 2026-02-25 13:07:34 CET; 11s ago
   Duration: 303ms
 Invocation: 93ffebc79da342eba8179b84d95a7487
       Docs: man:keyd(1)
    Process: 42971 ExecStart=/nix/store/apzpq5i83y8knkjliqhkah52awd8776m-keyd-2.5.0/bin/keyd (code=exited, status=255/EXCEPTION)
   Main PID: 42971 (code=exited, status=255/EXCEPTION)
         IP: 0B in, 0B out
         IO: 0B read, 0B written
   Mem peak: 2.5M
        CPU: 29ms

feb 25 13:07:34 <REMOVED> systemd[1]: keyd.service: Scheduled restart job, restart counter is at 5.
feb 25 13:07:34 <REMOVED> systemd[1]: keyd.service: Start request repeated too quickly.
feb 25 13:07:34 <REMOVED> systemd[1]: keyd.service: Failed with result 'exit-code'.
feb 25 13:07:34 <REMOVED> systemd[1]: Failed to start Keyd remapping daemon.

Here is the journalctl output.

feb 25 13:11:59 keyd[43682]: WARNING: failed to set effective group to "keyd" (make sure the group exists)
feb 25 13:11:59 kernel: input: keyd virtual keyboard as /devices/virtual/input/input71
feb 25 13:11:59 systemd-timesyncd[577]: Contacted time server 131.180.14.10:123 (1.nixos.pool.ntp.org).
feb 25 13:11:59 keyd[43682]: opendir: Permission denied
feb 25 13:11:59 kernel: input: keyd virtual pointer as /devices/virtual/input/input72
feb 25 13:11:59 systemd-logind[953]: Watching system buttons on /dev/input/event15 (keyd virtual keyboard)
feb 25 13:11:59 systemd[1]: keyd.service: Main process exited, code=exited, status=255/EXCEPTION
feb 25 13:11:59 systemd[1]: keyd.service: Failed with result 'exit-code'.
feb 25 13:11:59 systemd[1]: keyd.service: Scheduled restart job, restart counter is at 2.
feb 25 13:11:59 systemd[1]: Started Keyd remapping daemon.
feb 25 13:11:59 keyd[43690]: WARNING: failed to set effective group to "keyd" (make sure the group exists)
feb 25 13:11:59 kernel: input: keyd virtual keyboard as /devices/virtual/input/input73
feb 25 13:11:59 systemd-timesyncd[577]: Contacted time server 131.180.14.10:123 (1.nixos.pool.ntp.org).
feb 25 13:11:59 keyd[43690]: opendir: Permission denied
feb 25 13:11:59 kernel: input: keyd virtual pointer as /devices/virtual/input/input74
feb 25 13:11:59 systemd-logind[953]: Watching system buttons on /dev/input/event15 (keyd virtual keyboard)
feb 25 13:12:00 systemd[1]: keyd.service: Main process exited, code=exited, status=255/EXCEPTION
feb 25 13:12:00 systemd[1]: keyd.service: Failed with result 'exit-code'.
feb 25 13:12:00 systemd[1]: keyd.service: Scheduled restart job, restart counter is at 3.
feb 25 13:12:00 systemd[1]: Started Keyd remapping daemon.
feb 25 13:12:00 systemd-timesyncd[577]: Contacted time server 131.180.14.10:123 (1.nixos.pool.ntp.org).
feb 25 13:12:00 keyd[43699]: WARNING: failed to set effective group to "keyd" (make sure the group exists)
feb 25 13:12:00 kernel: input: keyd virtual keyboard as /devices/virtual/input/input75
feb 25 13:12:00 keyd[43699]: opendir: Permission denied
feb 25 13:12:00 kernel: input: keyd virtual pointer as /devices/virtual/input/input76
feb 25 13:12:00 systemd-logind[953]: Watching system buttons on /dev/input/event15 (keyd virtual keyboard)
feb 25 13:12:00 systemd[1]: keyd.service: Main process exited, code=exited, status=255/EXCEPTION
feb 25 13:12:00 systemd[1]: keyd.service: Failed with result 'exit-code'.
feb 25 13:12:00 systemd[1]: keyd.service: Scheduled restart job, restart counter is at 4.
feb 25 13:12:00 systemd[1]: Started Keyd remapping daemon.
feb 25 13:12:00 keyd[43707]: WARNING: failed to set effective group to "keyd" (make sure the group exists)
feb 25 13:12:00 kernel: input: keyd virtual keyboard as /devices/virtual/input/input77
feb 25 13:12:00 systemd-timesyncd[577]: Contacted time server 131.180.14.10:123 (1.nixos.pool.ntp.org).
feb 25 13:12:00 keyd[43707]: opendir: Permission denied
feb 25 13:12:00 kernel: input: keyd virtual pointer as /devices/virtual/input/input78
feb 25 13:12:00 systemd-logind[953]: Watching system buttons on /dev/input/event15 (keyd virtual keyboard)
feb 25 13:12:01 systemd[1]: keyd.service: Main process exited, code=exited, status=255/EXCEPTION
feb 25 13:12:01 systemd[1]: keyd.service: Failed with result 'exit-code'.
feb 25 13:12:01 systemd[1]: keyd.service: Scheduled restart job, restart counter is at 5.
feb 25 13:12:01 systemd[1]: keyd.service: Start request repeated too quickly.
feb 25 13:12:01 systemd[1]: keyd.service: Failed with result 'exit-code'.
feb 25 13:12:01 systemd[1]: Failed to start Keyd remapping daemon.

Please help :cry: I would really like to get keyd working so please do not just say “use katana” or some other tool.