Sudoers paths not working: Binary path doesn't match path to containing package

I’m trying to add the tc program to the sudoers file to run without a password prompt:

sudo = {
  enable = true;
  execWheelOnly = true;
  extraRules = [
    groups = [ "wheel" ];
    commands = [
      command = "${pkgs.iproute2}/bin/tc";
      options = [ "NOPASSWD" ];

For the most part this works. If I look at the generated sudoers file, I can see the path to the binary:

%wheel  ALL=(ALL:ALL)    NOPASSWD: /nix/store/9w8x9qzjkiy2jsa4zji31yxjdih92h97-iproute2-6.5.0/bin/tc

And if I specify that full path on the command line, it runs without a password prompt as expected.

However, this isn’t the binary that gets run by default on the command line:

❯ whereis tc
tc: /nix/store/l17rs3zv5kr2kwjvibvlaqzks8nhllj7-system-path/bin/tc

Since the paths don’t match, running sudo tc without the full path from the sudoers file doesn’t work, it prompts for a password.

So why do there appear to be two paths for this binary? What is the system-path location? It isn’t a package I can use in my nix config…

That is a derivation which collects all system wide installed packages and symlinks them together.

To solve this problem you either add a security wrapper for tc, see or use ${config.system.path}/bin/tc

1 Like

I guess that this is due to how whereis deals with symlinks exactly. The actual canonical path to the binary that will be run can be found with realpath $(which tc).

There was also a recent change in sudo behaviour that causes sudo to not match commands with their store paths, I reported the issue here:

The current best solution that I found, is to put /run/current-system/sw/bin/<binary name> in the sudoers rule, and make sure that the package is on the system path (by adding it to environment.systemPackages).

For stuff in your user env, like stuff managed by home-manager, I think you’d need to use something like /home/<user>/.local/state/nix/profiles/home-manager/home-path/bin.

1 Like