Why does `nixpkgs.config` exist?

We have some configuration options under nixpkgs.config that seem different from options in the config hierarchy. What I gather is that they can be set on nixpkgs before pkgs exist, so I’d assume they’re something needed at an even lower level. But, on the other hand, apparently they also can be set from modules using just nixpkgs.config.foo = true;, which seems to be hard to square with that idea.

I guess this is a good question to start unraveling my confusion: What is special about variables like cudaSupport and cudaCapabilities that necessitates them being in nixpkgs.config instead of an option just like, say, services.printing.enable?

They apparently also are an open ended set; nixpkgs.config.foobarbaz = true; happily and silently does nothing. There is a list in the manual of config options, but it seems to not include all of them—at least cudaCapabilities supposedly exists in addition to cudaSupport, but only the latter is documented there (although the page later mentions cudaCapabilities). Accordingly, they’re not found by the options search.

I assume there must be some good reason why these are different. Anyone care to enlighten a noob? :slight_smile:

cudaSupport and cudaCapabilities change the build of packages that use them, so they are build configuration and not system configuration. E.g. enabling cudaSupport builds Torch with CUDA support. Setting cudaCapabilities = [ "9.0" ] in addition to that will only build CUDA code with NVIDIA Hopper support.

Suppose that you use nixpkgs on a non-NixOS system. You still want to be able to configure whether packages should be built with CUDA support or not.

3 Likes

nixpkgs.config is for configuring the nixpkgs instance (allowing unfree, non-source, broken, insecure, …) or for groups of overrides across packages (TTS support, CUDA support, …) rather than having to override individual packages to all use the same flags.

I can’t say I’m a fan of the latter but I haven’t heard of a better alternative yet.

2 Likes

There have been some proposals over the years to turn packages into modules, rather than functions, and have some centralised set of options like NixOS.
It’s such a radical change that it’s very unlikely to be implemented, though.

The problem is not that it would be a radical change but that the module system would impose a prohibitively expensive performance hit on already massive evaluation times and memory usage.

Contributors and users would benefit a lot from more type safety and a more data-oriented packaging approach, which is one of the original motivations behind @davhau’s dream2nix. A very good introduction to the topic in a video:

The most recent contribution to that discussion I’ve seen about that is @roberth’s minimod, a minimal implementation of the module system that has the potential to strike the right balance between flexibility and performance.

4 Likes

Enabling cudaSupport (rocmSupport) in one program (say, torch) requires reconfiguring its transitive dependencies (e.g. ucc, magma, etc.). The easiest way to achieve consistency today is to just enable cudaSupport Nixpkgs-wide using config. However you do not have to do this NixOS-wide, e.g. you could instead:

{
  services.foobar.package = let pkgsCuda = import <nixpkgs> { config.cudaSupport = true; }; in
    pkgsCuda.foobar;
}

Yes, nixpkgs.config (today) is a freeformType and some options are explicitly declared and then documented: nixpkgs/pkgs/top-level/config.nix at 4028c38d07192e816424732781c371c8b9c649b7 · NixOS/nixpkgs · GitHub

1 Like

To elaborate on this: Nixpkgs itself has a “config” argument, whether it is used inside a NixOS configuration, or not. For example, if you’re using a standalone shell.nix, you might write it as:

let pkgs = import <nixpkgs> {
  config = {
    allowUnfree = true;
    cudaSupport = true;
    # etc.
  };
};
in
# ...

Given this, it is desirable to also be able to set these sorts of config options for the pkgs when you’re building a NixOS system - that’s what nixpkgs.config does. It being a 1-to-1 mapping to Nixpkgs’ config option is just a simple and straightforward way to do this, as opposed to e.g. duplicating all of its options in the module system.

2 Likes

Thanks, that’s interesting!

As a complete aside, and purely for what it’s worth[1], I tasked an LLM to describe some of the history around these topics yesterday—specifically, attempts to unify the module system and the package functions—although I didn’t realize the existence of nixpkgs.config was also related to the same topic before reading the explanations here. That answer also pointed me to dream2nix, although that video obviously goes to much more depth.

I’m sure it’s not an all-encompassing history, and I wouldn’t be surprised if it gets things subtly wrong and omits some aspects and developments, but it felt enlightening to me as someone who’s used Nix for half a year and has not been able to gather the information from all the normal places—no judgment on whether that’s true or false light so far. In the least it did alert me to the existence of things I didn’t know of and how they tie together.


  1. i.e. if anyone reads that, I won’t promise any return for time investment—I found it interesting, but I’m new and don’t know what I don’t know ↩︎