How to know which packages depends on a specific version of another package?

I use NixOS with the nixos-24.11 branch.
Recently I update the openssh from 9.9p1 to 9.9p2 with this command:

programs.ssh.package = pkgs.master.openssh

pkgs was overlaid with master branch before.
I use master branch openssh because it is the only branch having 9.9p2.

However, after that, in the nvd diff command, I also saw this line:

[C*]  #3  openssh  9.9p1 -> 9.9p1, 9.9p2

I think some packages are still depends on 9.9p1 openssh.
How can I find those packages out? Thanks.

Instead of creating an overlay where you set pkgs.master = master why don’t you create an overlay where you set pkgs.openssh = master.openssh?

2 Likes

nix-tree (3rd party tool) is useful for this, I find.

2 Likes

The built-in nix why-depends pointing at /run/current-system (or the generation you want to check) with --all would be my pick.

1 Like

Wouldn’t you need the full store path in that case? (Or you have to somehow assume that your config has no overrides relative to your inputs if you provide an arg like nixpkgs#package?)

Yeah, but that’s not hard to find on your typical desktop with a quick ls /nix/store | grep openssh, or a ls -l $(which ssh) or such, depending on how what you’re inspecting is exposed.

If you have a dozen generations, that can easily become a nightmare, I would not recommend grepping filenames in the store, and it wouldn’t be on PATH since they set the package for the ssh module to something else. If anything it’d be more effective to use nix-store commands.

You could use systemctl status for a system service, the path of the binary will be tracked. My point is, there are plenty of ways these paths are exposed if you need to get a handle on them.

That doesn’t make sense; they don’t know why the path is in their closure in the first place, else they wouldn’t be looking for why it’s in their closure… if they knew which service depended on it then there wouldn’t be a question to ask here.

There’s really only one way to find these paths: query the closure of the current system.

If OP really is against using a third-party tool, the sensible way to query this would be via nix-store --query --requisites, e.g.

for i in $(nix-store --query --requisites /run/current-system | grep openssh-9.9p1)
do
  nix why-depends --all /run/current-system $i
done

NB the big issue there is the for loop, it’s probably going to be annoyingly slow if there’s more than like 5 results.

I’d still personally use nix-tree, because that closure calculation penalty only happens once when I open the program, and it gives some more IMO useful information like overall closure size and net closure size increase due to each package, and allows sorting by such. Though the downside is lacking the --precise flag and general scriptability, I suppose.

2 Likes

That should be quite uncommon, as one generation is unlikely to depend on that many instances of the same openssh version. It’d take a very hairy override mess to get there.

And yep, filtering it down to a specific generation is a much more sensible approach.

Though I do wonder what the speed difference between this and grepping the nix store paths directly is in practice, even with many generations it’s probably a minute or two at the absolute worst, which isn’t much for a one-off command, and nix why-depends will only give you results for the paths you actually depend on… But yeah, I should probably start knowing the query commands by heart.

1 Like

Yeah there’s too much to keep track of in nix across its over 130 manpages… I end up looking up the nix-store --query flags every time, especially given the oddly similar naming.

1 Like

I set up the overlay with flake like this when I start using nixos as a newbie:

{
  inputs,
  system,
  ...
}:
let
  overlay-unstable = final: prev: {
    unstable = import inputs.nixpkgs-unstable {
      inherit system;
    };
  };

  overlay-master = final: prev: {
    master = import inputs.nixpkgs-master {
      inherit system;
    };
  };
in
{
  nixpkgs = {
    overlays = [
      overlay-unstable
      overlay-master
    ];
  };
}

where the nixpkgs-master and nixpkgs-unstable points to flakes input.

I forgot where I copy and paste those code.

Is it wrong?
How can I setup to use pkgs.openssh = master.openssh instead?
Thanks

This is good!
The 9.9p1 is a dependencies of password-store (pass) !
Thanks so much!

Something like:

  overlay-master = final: prev: {
    openssh = inputs.nixpkgs-master.legacyPackages.${system}.openssh;
  };

(untested)

1 Like