How to detect redundant Nix packages?

Cross-post from Unix Stack Exchange:

Say I have services.openssh.enable = true; and environment.systemPackages contains “openssh”. The latter is redundant, because the OpenSSH service requires the “openssh” package. How do I detect such duplicates?

In trivial cases a text match would give a pretty good indication of a duplicate, but enabling for example service.xserver.desktopManager.xfce installs a bunch of packages, any one of which I might have listed in environment.systemPackages. Is it possible to detect such duplicates as well?

Perhaps try nix-collect-garbage.

There’s also nix-store --optimise to hard-link duplicate packages.

https://nixos.org/nixos/nix-pills/garbage-collector.html
https://nixos.wiki/wiki/Storage_optimization#Optimizing_the_store

Would those help me minimize the configuration? I thought those tools left the configuration alone…

If you are referring to your configuration.nix file, no it does not, as it’s meant to be declarative by the user.

But if you are worried about duplicating packages taking up unnecessary space, those tools can help out, you may even set college garbage on a cron job.

environment.systemPackages is defined as a types.listOf types.package. If you look into <nixpkgs/lib/types.nix> you’ll see that each nixos module type has a merge semantic that can be overridden. Potentially it could be edited to emit a warning on duplicate entries.

Without changing anything you can also look at the current list with nix repl:

nix-repl> map (p: p.name) (import <nixpkgs/nixos> {}).config.environment.systemPackages

In my list I have a lot of duplicates for the shadow package.

Continuing @zimbatm line of thought, we can extract even more information from configuration. I’ll do tests against default container config, but you can adapt it to your configuration:

[danbst@station:~/dev/nixpkgs]$ nix eval $'(
    let sysPkgs = (import ./nixos { configuration = { 
            boot.isContainer = true; 
        }; }).options.environment.systemPackages; 
    in {
      pkgs = builtins.foldl\' 
         ( acc: x: acc // { ${x.name} = ( acc.${x.name} or []) ++ [x.meta.position]; })
         {} sysPkgs.value; 
      modules = sysPkgs.files; 
    })' --json | jq .
{
  "modules": [
    "/home/danbst/dev/nixpkgs/nixos/modules/tasks/swraid.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/tasks/network-interfaces.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/tasks/filesystems.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/tasks/bcache.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/system/boot/systemd.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/system/boot/kexec.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/services/system/dbus.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/services/networking/firewall.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/services/networking/dhcpcd.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/security/sudo.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/security/polkit.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/security/pam.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/programs/shadow.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/programs/bash/bash.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/misc/documentation.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/misc/documentation.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/misc/documentation.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/installer/tools/tools.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/config/users-groups.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/config/system-path.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/config/resolvconf.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/config/i18n.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/config/xdg/mime.nix",
    "/home/danbst/dev/nixpkgs/nixos/modules/config/fonts/fontconfig.nix"
  ],
  "pkgs": {
    "acl-2.2.53": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/acl/default.nix:27"
    ],
    "attr-2.4.48": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/attr/default.nix:31"
    ],
    "bash-interactive-4.4-p23": [
      "/home/danbst/dev/nixpkgs/pkgs/shells/bash/4.4.nix:110",
      "/home/danbst/dev/nixpkgs/pkgs/shells/bash/4.4.nix:110",
      "/home/danbst/dev/nixpkgs/pkgs/shells/bash/4.4.nix:110"
    ],
    "bcache-tools-1.0.7": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/filesystems/bcache-tools/default.nix:41"
    ],
    "bind-9.14.4": [
      "/home/danbst/dev/nixpkgs/pkgs/servers/dns/bind/default.nix:81"
    ],
    "bzip2-1.0.6.0.1": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/compression/bzip2/default.nix:40"
    ],
    "command-not-found": [
      "/home/danbst/dev/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix:13"
    ],
    "coreutils-8.31": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/misc/coreutils/default.nix:124"
    ],
    "cpio-2.12": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/archivers/cpio/default.nix:36"
    ],
    "curl-7.65.3": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/networking/curl/default.nix:110"
    ],
    "dbus-1.12.16": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/dbus/default.nix:86",
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/dbus/default.nix:86"
    ],
    "dhcpcd-7.2.3": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/networking/dhcpcd/default.nix:40"
    ],
    "diffutils-3.7": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/text/diffutils/default.nix:25"
    ],
    "dosfstools-4.1": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/filesystems/dosfstools/default.nix:20"
    ],
    "e2fsprogs-1.45.3": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/filesystems/e2fsprogs/default.nix:58"
    ],
    "findutils-4.6.0": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/misc/findutils/default.nix:44"
    ],
    "fontconfig-2.12.6": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/fontconfig/default.nix:73"
    ],
    "fuse-2.9.9": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/fuse/common.nix:87"
    ],
    "fuse-3.6.2": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/fuse/common.nix:87"
    ],
    "gawk-4.2.1": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/text/gawk/default.nix:59"
    ],
    "getconf-1003.1-2008": [
      "/home/danbst/dev/nixpkgs/pkgs/build-support/trivial-builders.nix:7"
    ],
    "getent-1003.1-2008": [
      "/home/danbst/dev/nixpkgs/pkgs/build-support/trivial-builders.nix:7"
    ],
    "glibc-2.27": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/glibc/default.nix:127"
    ],
    "glibc-locales-2.27": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/glibc/locales.nix:67"
    ],
    "gnugrep-3.3": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/text/gnugrep/default.nix:45"
    ],
    "gnused-4.7": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/text/gnused/default.nix:22"
    ],
    "gnutar-1.32": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/archivers/gnutar/default.nix:45"
    ],
    "gzip-1.10": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/compression/gzip/default.nix:22"
    ],
    "iproute2-5.2.0": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/iproute/default.nix:50"
    ],
    "iptables-1.8.3": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/iptables/default.nix:30"
    ],
    "iputils-20190709": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/iputils/default.nix:41"
    ],
    "kexec-tools-2.0.19": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/kexectools/default.nix:23"
    ],
    "less-551": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/misc/less/default.nix:19"
    ],
    "libcap-2.27": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/libcap/default.nix:56"
    ],
    "libressl-2.9.2": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/libressl/default.nix:40"
    ],
    "linux-pam-1.3.1": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/pam/default.nix:61"
    ],
    "man-db-2.7.5": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/misc/man-db/default.nix:64"
    ],
    "mdadm-4.1": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/mdadm/default.nix:34"
    ],
    "nano-3.2": [
      "/home/danbst/dev/nixpkgs/pkgs/applications/editors/nano/default.nix:49"
    ],
    "ncurses-6.1-20190112": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/ncurses/default.nix:151"
    ],
    "net-tools-1.60_p20170221182432": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/net-tools/default.nix:31"
    ],
    "nix-2.2.2": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/package-management/nix/default.nix:108"
    ],
    "nix-bash-completions-0.6.7": [
      "/home/danbst/dev/nixpkgs/pkgs/shells/bash/nix-bash-completions/default.nix:31"
    ],
    "nix-info": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/nix/info/default.nix:7"
    ],
    "nixos-build-vms": [
      "/home/danbst/dev/nixpkgs/nixos/modules/installer/tools/tools.nix:15"
    ],
    "nixos-enter": [
      "/home/danbst/dev/nixpkgs/nixos/modules/installer/tools/tools.nix:56"
    ],
    "nixos-generate-config": [
      "/home/danbst/dev/nixpkgs/nixos/modules/installer/tools/tools.nix:37"
    ],
    "nixos-help": [
      "/home/danbst/dev/nixpkgs/pkgs/build-support/trivial-builders.nix:7"
    ],
    "nixos-install": [
      "/home/danbst/dev/nixpkgs/nixos/modules/installer/tools/tools.nix:20"
    ],
    "nixos-manpages": [
      "/home/danbst/dev/nixpkgs/pkgs/build-support/trivial-builders.nix:7"
    ],
    "nixos-manual-html": [
      "/home/danbst/dev/nixpkgs/nixos/doc/manual/default.nix:258"
    ],
    "nixos-option": [
      "/home/danbst/dev/nixpkgs/nixos/modules/installer/tools/tools.nix:45"
    ],
    "nixos-rebuild": [
      "/home/danbst/dev/nixpkgs/nixos/modules/installer/tools/tools.nix:29"
    ],
    "nixos-version": [
      "/home/danbst/dev/nixpkgs/nixos/modules/installer/tools/tools.nix:52"
    ],
    "openresolv-3.9.1": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/networking/openresolv/default.nix:34"
    ],
    "openssh-7.9p1": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/networking/openssh/default.nix:108"
    ],
    "patch-2.7.6": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/text/gnupatch/default.nix:46"
    ],
    "perl-5.28.2": [
      "/home/danbst/dev/nixpkgs/pkgs/development/interpreters/perl/default.nix:167"
    ],
    "polkit-0.116": [
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/polkit/default.nix:86",
      "/home/danbst/dev/nixpkgs/pkgs/development/libraries/polkit/default.nix:86"
    ],
    "procps-3.3.15": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/procps-ng/default.nix:48"
    ],
    "rsync-3.1.3": [
      "/home/danbst/dev/nixpkgs/pkgs/applications/networking/sync/rsync/default.nix:27"
    ],
    "shadow-4.6": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89",
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/shadow/default.nix:89"
    ],
    "shared-mime-info-1.12": [
      "/home/danbst/dev/nixpkgs/pkgs/data/misc/shared-mime-info/default.nix:18"
    ],
    "strace-5.2": [
      "/home/danbst/dev/nixpkgs/pkgs/development/tools/misc/strace/default.nix:25"
    ],
    "sudo-1.8.27": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/security/sudo/default.nix:67"
    ],
    "systemd-242": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/systemd/default.nix:220"
    ],
    "texinfo-interactive-interactive-6.5": [
      "/home/danbst/dev/nixpkgs/pkgs/development/tools/misc/texinfo/common.nix:46"
    ],
    "time-1.9": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/misc/time/default.nix:13"
    ],
    "util-linux-2.33.2": [
      "/home/danbst/dev/nixpkgs/pkgs/os-specific/linux/util-linux/default.nix:73"
    ],
    "which-2.21": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/system/which/default.nix:4"
    ],
    "xz-5.2.4": [
      "/home/danbst/dev/nixpkgs/pkgs/tools/compression/xz/default.nix:29"
    ]
  }
}

So now we know which NixOS modules do add at least one pkg to systemPackages, and we know which pkgs are added twice or more to this list. The search circle for pkg duplicates is greatly reduced now!

3 Likes