xremap / nix-flake

MIT License
38 stars 10 forks source link

homeManagerModule with input group and udev requiring sudo #70

Closed rytswd closed 1 month ago

rytswd commented 1 month ago

This may well be misconfiguration at my end, but I am failing to get the Xremap to start up from the systemd cleanly with home-manager config, and I'd have to start Xremap using sudo once, and only then all the home-manager bindings seem to work fine. The below is the gist of what I have at the moment.

My home-manager module for Xremap, xremap/default.nix:

{ pkgs
, lib
, config
, inputs
, ...}:

{
  imports = [ inputs.xremap.homeManagerModules.default ];

  services.xremap = {
    enable = true;
    withWlroots = true;
    # watch = true;
    deviceNames = [
      "Asus\ Keyboard"
    ];
    yamlConfig = (builtins.readFile ./xremap.yaml);
  };
}

In my home-manager config:

    imports = [
      # ...
      ../../modules/xremap
      # ...
    ];

My NixOS config for udev:

    services.udev = {
      # NOTE: Xremap requires the following:
      # https://github.com/xremap/xremap?tab=readme-ov-file#running-xremap-without-sudo
      extraRules = ''
        KERNEL=="uinput", GROUP="input", MODE="0660", TAG+="uaccess"
      '';
    };

My user is set with input group as well as wheel. When I do sudo xremap, though, I cannot seem to get the wlroots to find the application context, and thus need to run without one. I'm probably doing something incorrect with udev, but any support would be much appreciated!

VTimofeenko commented 1 month ago

failing to get the Xremap to start up from the systemd cleanly with home-manager config

At a glance the config looks OK. What is the output of systemctl --user status xremap ran as the user managed by home-manager? Anything in logs? journalctl --user -u xremap

I'd have to start Xremap using sudo once, and only then all the home-manager bindings seem to work fine

When I do sudo xremap, though, I cannot seem to get the wlroots to find the application context, and thus need to run without one

Can you clarify the sequence here?

sudo uses root's environment; xremap would not be able to locate the DE socket thus app-specific bindings would probably not work.

Also, which desktop environment (sway/hyprland/something else) are you using?

rytswd commented 1 month ago

Hi @VTimofeenko, thanks for the quick response!

When Xremap is run as a non-root user, I get the following error:

Error: Failed to prepare an output device: Permission denied (os error 13)

This is true for both systemd as well as when I manually trigger the Xremap (I downloaded the latest binary directly to test against). And as mentioned above, this error goes away after running it with sudo once.

So the sequence to get Xremap to work is the following:

  1. Start up and login as a non-root user
  2. At this point, I can see systemctl --user status xremap in a failed state
  3. I can see the error Error: Failed to prepare an output device: Permission denied (os error 13) with journalctl
  4. Run Xremap with sudo manually (something like sudo ./Downloads/xremap ./Coding/xremap/xremap.yaml --device "Asus Keyboard")
  5. Confirm that I do not get any error (if I try to use application context based mapping, I'd get an error, which is expected when running it as root)
  6. Kill the process from step#4, and restart systemd with systemctl --user restart xremap
  7. Confirm that I do not get any error, and Xremap works correctly including application context

I'm using Niri (https://github.com/YaLTeR/niri), but I could repro this with Hyprland as well.

VTimofeenko commented 1 month ago

Potential solution:

Have you tried using the non-home manager user module? Here's a sample flake, you would need to import the inputs.xremal-flake.nixosModules.default, set services.xremap.serviceMode = "user" and specify the user.

The user mode automatically adds the user to uinput and input (source)

If you want to disect this further:

This is very odd. AFAIK xremap does not change device permissions by itself -- that's kinda the point of udev. One potential idea is that udev is not triggered before step 4. DE is not relevant in this case.

Can you provide:

  1. Outputs of id and groups at login
  2. Outputs of getfacl /dev/input/event0at step 1 and 6

Also worth running udevadm monitor --property --subsystem-match=input while everything is happening and check the messages as to what exactly is going on.

rytswd commented 1 month ago

Thanks for the reference -- with the reference to how it's handled with NixOS module, I could finally find what I was missing!

My user was configured with input group, but it wasn't part of uinput. In fact, I didn't even have the uinput group defined, and that was because I didn't have hardware.uinput.enable = true; in my config. Once I added that, and made sure the login user is also a part of uinput group, I could get the Xremap to work smoothly with systemd!

So, I think the below is the NixOS configuration needed for home-manager based Xremap setup:

    # Ensure uinput group is made available
    hardware.uinput.enable = true;
    services.udev = {
      # NOTE: Xremap requires the following:
      # https://github.com/xremap/xremap?tab=readme-ov-file#running-xremap-without-sudo
      extraRules = ''
        KERNEL=="uinput", GROUP="input", TAG+="uaccess"
      '';
    };

With that in place, once a user is a part of both input and uinput group, the non-root user can run Xremap.