Over the course of reading the Nix manual, reading the Nixpkgs manual, reading the Nix Pills, and performing my own experiments, I have accumulated quite a few “open questions.”

I leave them at the bottom of each post, and they help ease my mind: writing them down allows me to forget them. They are not lurking in the darker corners of my brain, distracting me as I try to go about my day. They will be there for me when I need them, and that is a calming thought.

Now, I’m not done learning Nix. But I have read all of the official documentation, at this point, and it is time to enter into a new chapter of my Nix journey: I am leaving the warm embrace of the manuals, and setting off on my own. And what better place to start by going through my open questions?

All 160 of them.

That’s a lot! But I have written a lot of blog posts. That’s only 4 questions per post, on average, which actually feels a little low to me.

And besides, it’s not really 160 open questions. I expect that I know the answer to most of them, by now. And lots of them are subjective “why is Nix like this”-type questions that I don’t actually need to answer.

So… let’s see if I’m right? Be back soon.

Soon:

Okay, so I went through every single question, and:

  • I know the answer to 66 of them.
  • I think I know the answer to 11 more, but I want to follow up on something about them.
  • 26 are bad questions: either they’re subjective or they don’t have answers or their answers are not actually satisfying in any way.
  • Which leaves 57 questions that I don’t know the answer to.

Okay. That’s not… too bad…

But I certainly have my work cut out for me. Let’s start with the easy stuff:

Answers I feel pretty good about

  • What is the difference between a “derivation” and a “store derivation”?
    • “Store derivation” refers to a .drv file, “derivation” is a fuzzy word that could mean any of like three different things.
  • How does a derivation turn into a “result” or an “output path”? When does a derivation “produce” something?
    • The primitive operation is nix-store --realise, but many other commands realize derivations: nix-build, nix-env, nix-shell, etc.
  • How do I configure the location of the Nix binary cache (or other “substituters,” if I recall the terminology correctly)?
  • What/why is nix-shell '<nixpkgs>' --attr pan?
    • <nixpkgs> is a file path that evaluates to a function of no arguments that returns an attribute set; --attr selects a specific attribute within that attribute set. That gives you a derivation, and nix-shell plops you into a shell with the build-time dependencies of that derivation.
  • What is NIX_PATH?
    • This is a variable kinda like PATH, colon-separated directories that are searched to resolve <foo> expressions, but it can also contain named elements: nixpkgs=/path/to/the/thing.
  • What does the weird comment mean about “appending channels” to NIX_PATH?
  • What is ~/.nix-defexpr?
  • What is ~/.nix-profile?
    • Symlink to the current user environment built by nix-env.
  • What is ~/.nix-channels?
    • Tiny text file listing channel names and URLs. Used by nix-channel commands.
  • Why does nix-env -qa git print the same line three times?
    • Package names are dumb and broken. I’m really seeing:

      $ nix-env -qa git --json | jq keys
      [
        "nixpkgs.git",
        "nixpkgs.git-doc",
        "nixpkgs.gitFull"
      ]
      
  • Why doesn’t nix-env -qa behave like a search?
    • It takes a regex.
  • How do I search for packages by name using nix-env?
    • Use a regex.
  • Why does nix-shell download so many packages? What are they for?
    • It downloads the packages in the standard environment, usually – it’s entirely dependent on the packages you invoke it with.
  • Why does every invocation of nix-env take 30 seconds before it does anything?
    • Package names are dumb and broken.
  • How do I collect garbage without making my next invocation of nix-shell -p hello redownload all the stuff it needs to be a shell?
  • Why does the manual explicitly call out upgrading Nix? Will it not be upgraded through “normal” means? Do I have to upgrade it separately?
    • No. It’s the same as any other package. Note that there is also nix upgrade-nix, which does not do what you think it does, or what you want it to do.
  • Why is ~/.nix-defexpr not just a symlink to nixpkgs?
    • Because you might have multiple channels.
  • Why does Nix call what seem to be associative arrays, or records, or something “sets”?
    • The term “set” is just shorthand for “attribute set.”
  • Does nix-env -iA nixpkgs.hello actually do anything if hello is already installed?
    • Not if it’s the same derivation; but it will replace it if not.
  • Where is the Nix configuration file?
    • ~/.config/nix/config.nix
  • What are “outputs” (as in keep-outputs)?
  • What does keep-derivations do? I’m still not really clear on the term “derivations”.
  • What is a manifest.nix?
  • What does the function mkDerivation actually do? What does it “return”? What side effects does it have?
  • Why does Nix call maps “sets”?
    • Duplicate; see above.
  • Are paths a first-class type in Nix?
    • Yes.
  • What is a hook?
  • Do I have to source $stdenv/setup? If so, why?
    • Nope! But it’s pretty handy, and saves a lot of work.
  • When are the side effects of fetchurl actually executed?
    • fetchurl evaluates to a derivation, so whenever that derivation is “realized” (built).
  • What exactly does callPackage call functions with?
    • The Nixpkgs “fixpoint” set, i.e., the thing that import <nixpkgs> {} returns.
  • Why does import /Users/ian/src/nixpkgs give me a function back?
    • So you can pass optional arguments like system or config to customize Nixpkgs.
  • How do I make my own ianpkgs without importing things from the “main” nixpkgs? What would a minimal default.nix look like?
    • The Nix Pills series does a pretty good job of walking through a derivation from actual scratch.
  • How do I find my platform identifier without building Nix from scratch?
    • builtins.currentSystem
  • If builder is a derivation that produces multiple files, what binary does it run?
    • The builder technically can be a derivation, but it’s coerced to a path, so the builder would have to evaluate to a single file. If it evaluates to a directory, you have to specify the path to the executable you want.
  • Are paths actually a different type at runtime, or are they really strings?
    • They really are different, and are more complicated than just strings, due to the file-filtering stuff.
  • Why does $stdenv/setup require one of $dev or $out to exist?
  • How can I explicitly register a runtime dependency?
    • You can’t, at least in the way that I was thinking when I asked the question. This is only possible by putting a reference to the dependency in the output path.
  • Does toString have the same behavior as Nix’s stringification of derivation attributes?
    • Yes; it just looks at the outPath attribute:

      nix-repl> builtins.toString { outPath = "hi"; }
      "hi"
      
  • What is a pure/impure shell?
  • What is manifest.nix?
    • Duplicate; see above.
  • What’s the difference between a package and a derivation?
    • This is fuzzy, difficult question to answer. A derivation is like the “recipe” to produce a package, or a “description” of the package. Or sometimes it’s used to refer to the package itself. The terminology is vague and confusing, as far as I can tell.
  • How can I ask Nix to show me runtime dependencies of an output?
    • nix-store --query --references or nix-store --query --requisites, for the reqursive version. Note that Nix doesn’t really have a concept of a “runtime” reference, though, and this will include build-time dependencies in the case that you have propagatedBuildInputs.
  • Are runtime dependencies known per-derivation, or per-output?
    • Per-output.
  • How can I inspect / pretty print a store derivation?
    • nix show-derivation
  • What’s the difference between nix-store --dump and nix-store --export?
    • --dump gives you the contents of the store path; --export gives you the contents of the store path plus the relevant database entries.
  • What does nix-env -i /nix/store/store-path do?
    • I mean, it does the thing you expect; it’s just undocumented.
  • How do I (locally) “fork” a derivation?
  • How can I evaluate an option to see its current/default value?
    • nix show-config
  • What the hell does keep-outputs do?
    • Duplicate; see above.
  • What happens if two packages produce outputs with the same name? Like what if I install /nix/store/foo-1.0/bin/foo and /nix/store/bar-1.0/bin/foo – what ends up in ~/.nix-profile/bin/foo?
  • Why is nix-env -u trying to upgrade my python3 to some weird alpha version?
  • How do I print all output paths of a derivation?
    • nix show-derivation, or nix-store --query --outputs.
  • What is derivation.override? A method?
    • Yeah, essentially, in the let-over-lambda sense. The Nix Pills series walks through the implementation.
  • How do I use derivation.override?
  • Why is there buildEnv – a function – in the top-level of Nixpkgs, when I learned before that nix-env required all top-level things to be derivations?
  • What is “the fixed-point used by Nixpkgs”? What does that mean? Why is that term never defined or explained?
    • Nix Pills does explain the term; but yeah, basically this is referring to the giant attribute that the function that is Nixpkgs returns, after applying user overrides and overlays and such.
  • Why does the repl print the drvPath instead of the outputPath?
    • It actually instantiates the derivation and puts it in your store.
  • What’s the point of .drv files?
    • Provides useful query operations, and gives a pretty clean separation between instantiation and realization.
  • How do I add a shell.nix file to my gcroots?
  • Why does the fixupPhase move doc directories around?
    • Okay, so basically: this is because of the default behavior of man, when you don’t specify an explicit MANPATH.

      Here is my MANPATH:

      $ manpath | tr ':' '\n'
      /usr/local/share/man
      /usr/share/man
      /Library/Apple/usr/share/man
      /Users/ian/.nix-profile/share/man
      /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/share/man
      /Library/Developer/CommandLineTools/usr/share/man
      

      Where does that come from? Wellllll… it’s enormously complicated. The answer to that question will not fit in this blog post. But you can see that /Users/ian/.nix-profile/share/man is in there, but /Users/ian/.nix-profile/man is not, so it makes sense to move foo-1.0/man to foo-1.0/share/man.1 That way when you install such a package, you will be able to run man foo and everything will work okay.

      But why would the foo derivation create foo-1.0/man in the first place? Why wouldn’t it create foo-1.0/share/man directly?

      Well, it might. But it might not: Nixpkgs is a big place, and packages a lot of software, not all of which is going to put man pages in the same place. So it makes sense to impose some consistency on the universe of packages after the fact, in a way that does not require modifying any make rules or anything. See that footnote above1 for an explanation of why share/man is preferable to man.

  • Why does nix repl keep printing errors about unfree packages when I just ask it to evaluate the top-level pkgs expression?
    • Because evaluating derivations at the repl actually instantiates the derivations and puts them in your store.
  • Does Nix not explicitly distinguish between runtime and build-time dependencies?
  • If I use an override or an overlay or whatever, does that only affect nix-env? Or does that affect any Nix command?
    • This is a Nixpkgs thing, so it will affect anything that imports <nixpkgs>.
  • How can I see the hash for a git repository, ala nix-prefetch-url?
  • How does Nix calculate the set of references for an output?
  • Can I have a dependency that only shows up in nix-shell, without being a build-time dependency of my derivation?
    • No; this doesn’t make sense. All nix-shell does is re-create the environment of a derivation, which includes all build-time dependencies.

Answers that I kinda basically get, but maybe should look into it further

  • What is the Nix database, and what is stored there?

    • This probably deserves a post of its own, but basically it stores metadata about paths in the store, like what other paths they reference, and whether or not they’re valid. But it also stores info about derivation outputs, and I don’t really understand the purpose of that.
  • When I get a binary cached package, do I still download and keep all the build-time dependencies?

    • I assume the answer is “no,” because it’s not necessary. But I don’t know if keep-outputs = true changes this answer. I don’t expect it to, but let’s check empirically.

      $ nix show-derivation nixpkgs.hello | jq '.[] |= { outputs, inputSrcs, inputDrvs }'
      
      {
        "/nix/store/mic03kwmyphr3pd9l0rrq28cf60b215s-hello-2.10.drv": {
          "outputs": {
            "out": {
              "path": "/nix/store/qwn4c03x5s1ydajfbqwdv236qkajpa4j-hello-2.10"
            }
          },
          "inputSrcs": [
            "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"
          ],
          "inputDrvs": {
            "/nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv": [
              "out"
            ],
            "/nix/store/apghmhf48v3d381nagi9sa86fprvsl6c-bash-4.4-p23.drv": [
              "out"
            ],
            "/nix/store/kfkii8d3rkwa1x7icr90bn8gbb6g8pzi-stdenv-darwin.drv": [
              "out"
            ]
          }
        }
      }
      

      So one “build time dependency” of hello is the output called out produced by the derivation /nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv. In other words, the hello source code.

      I think I can instantiate that derivation all by itself, to see the output path? I’m assuming it’s the src attribute…

      $ nix-instantiate '<nixpkgs>' -A hello.src
      warning: you did not specify '--add-root'; the result might be removed by the garbage collector
      /nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv
      

      Yep! And now I can find the output:

      $ nix show-derivation /nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv | jq '.[] |= .outputs'
      
      {
        "/nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv": {
          "out": {
            "path": "/nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz",
            "hashAlgo": "sha256",
            "hash": "31e066137a962676e89f69d1b65382de95a7ef7d914b8cb956f41ea72e0f516b"
          }
        }
      }
      

      Er, I also could have just done:

      $ nix-store --query --outputs /nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv
      /nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz
      

      Anyway. So the question is: when I install hello, will I also download the path /nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz? What about the /nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv?

      I don’t know the answer. I would be very surprised if it downloads hello-2.10.tar.gz, because that’s completely unnecessary. But I do expect it to put hello-2.10.tar.gz.drv in the store, because that’s a reference of the hello-2.10.drv file, and Nix doesn’t want a path in the store that is “incomplete” – that is missing some of its references.

      Let’s see if I’m right?

      $ nix-collect-garbage
      finding garbage collector roots...
      removing stale temporary roots file '/nix/var/nix/temproots/94738'
      removing stale temporary roots file '/nix/var/nix/temproots/94712'
      deleting garbage...
      deleting '/nix/store/mic03kwmyphr3pd9l0rrq28cf60b215s-hello-2.10.drv'
      deleting '/nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv'
      deleting '/nix/store/trash'
      deleting unused links...
      note: currently hard linking saves 0.00 MiB
      2 store paths deleted, 0.00 MiB freed
      

      Alright. Moment of truth:

      $ nix-env -iA nixpkgs.hello
      installing 'hello-2.10'
      these paths will be fetched (0.02 MiB download, 0.07 MiB unpacked):
        /nix/store/qwn4c03x5s1ydajfbqwdv236qkajpa4j-hello-2.10
      copying path '/nix/store/qwn4c03x5s1ydajfbqwdv236qkajpa4j-hello-2.10' from 'https://cache.nixos.org'...
      building '/nix/store/76wq9wqpszy173w5f4dn6fnv76lbsdwc-user-environment.drv'...
      created 1040 symlinks in user environment
      

      Okay. So we only fetched one path… but that’s expected. Because we’re able to produce the .drv files locally, from the definitions in Nixpkgs. And indeed, we did create the .drv:

      $ ls /nix/store/mic03kwmyphr3pd9l0rrq28cf60b215s-hello-2.10.drv
      /nix/store/mic03kwmyphr3pd9l0rrq28cf60b215s-hello-2.10.drv
      

      As well as its references:

      $ ls /nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv
      /nix/store/94ckk990hrnzjbk2062acmwxajpg64gf-hello-2.10.tar.gz.drv
      

      But we did not create the output:

      $ ls /nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz
      ls: cannot access '/nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz': No such file or directory
      

      Okay. So it works the way I expected.

  • Do “substitutes” live in the Nix database or not?

    • Just, like, empirically… no? This is an unusually false claim for the manual to make, though, and I couldn’t tell you where substituters do live, so I should look into a little bit. Like, it’s probably cached locally, right?

      I look it up, and find that substitutes are cached in ~/.cache/nix:

      $ sqlite3 ~/.cache/nix/binary-cache-v6.sqlite .schema
      
      CREATE TABLE BinaryCaches (
          id        integer primary key autoincrement not null,
          url       text unique not null,
          timestamp integer not null,
          storeDir  text not null,
          wantMassQuery integer not null,
          priority  integer not null
      );
      CREATE TABLE sqlite_sequence(name,seq);
      CREATE TABLE NARs (
          cache            integer not null,
          hashPart         text not null,
          namePart         text,
          url              text,
          compression      text,
          fileHash         text,
          fileSize         integer,
          narHash          text,
          narSize          integer,
          refs             text,
          deriver          text,
          sigs             text,
          ca               text,
          timestamp        integer not null,
          present          integer not null,
          primary key (cache, hashPart),
          foreign key (cache) references BinaryCaches(id) on delete cascade
      );
      CREATE TABLE LastPurge (
          dummy            text primary key,
          value            integer
      );
      

      They’re still called BinaryCaches, but those are our substitutes.

  • What is the “type” of a derivation?

    • It’s an attribute set containing the attribute { type = "derivation"; }, but it’s also… more than that?
  • How does nix-env --set-flag work?

    • I assume this just alters the manifest.nix, and nix-env commands know to parse manifest.nix before building the environment.
  • How can I make nix-shell use zsh?

    • I think just ignoring --rcfile will get me there… it is weirdly convoluted and annoying, though. This deserves its own post.
  • Is there a better way to see outdated packages?

  • Are derivations sets or not? Why do they print differently? What makes them different or special or magical?

    • Sort of a duplicate; { type = "derivation"; } is all it takes to make them print differently in nix repl.
  • Can I install my macOS GUI apps with Nix?

    • I think I could, but I can’t think of any reason why I would want to. Basically all macOS GUI apps use something like Sparkle to update themselves, so it’s not like they’d stay in sync anyway. I should check on Emacs, though.

      Let’s see… we’ve got nixpkgs.emacs and nixpkgs.emacsMacport. sd nix info emacsMacport tells me:

      This is the “Mac port” addition to GNU Emacs 26. This provides a native GUI support for Mac OS X 10.6 - 10.12. Note that Emacs 23 and later already contain the official GUI support via the NS (Cocoa) port for Mac OS X 10.4 and later. So if it is good enough for you, then you don’t need to try this.

      Hmm. Is emacs good enough for me? Let’s try it and see…

      Oooh wow. Performance is noticeably terrible. Like, just redraws are visibly slow. Let’s try the emacsMacport

      Huh! Running emacs now opens a terminal instance of Emacs. That’s kinda funny. Not really what I was going for, but sure. So uhhh…

      $ open ~/.nix-profile/Applications/Emacs.app
      No application knows how to open file:///Users/ian/.nix-profile/Applications/Emacs.app/ (Error Domain=NSOSStatusErrorDomain Code=-10814 "kLSApplicationNotFoundErr: E.g. no application claims the file" UserInfo={_LSLine=1479, _LSFunction=runEvaluator}).
      

      Hmm. I open it via Finder, and now it launches normally when I use open too. Weird. Something about that… made it realize it was an app? I have no idea. Anyway, it seems to work great. Performance feels only the normal amount of sluggish. I will probably gripe in the future if this turns out not to work right for some reason.

  • Does Nix install all build-time dependencies of a package?

    • Duplicate; see above.
  • Is Hydra responsible for populating https://cache.nixos.org?

    • I thought I knew the answer when I asked this – I thought it was obviously “yes” – but I have no idea how to check this.

      This is surprisingly hard to answer. I google furiously. I search through the NixOS organization on GitHub. I come up with no answers.

      I can find comments on the NixOS Discourse that confirm this; that make this claim. But nothing authoritative. Not that I don’t believe those comments, just… why isn’t this vital feature described in the Hydra README or manual or something?

      Hmm. Let’s look through the Hydra source.

      I find S3Backup.pm, which seems to be uploading build results to a configurable S3 bucket. But that file has barely changed over the last eight years. I think this is some random other thing.

      Hmm.

      Searching through IRC logs returns tons of references to Hydra populating the binary cache.

      So the code must be there. I just can’t find it using GitHub search. Time to clone, and get real search…

      Okay, I think it’s this bit. I sort of don’t bother to read the whole thing. I have lost the will to care about this any more.

      It’s strange to me that this is just known… and even I assumed this was the case. But I can’t find it actually written down anywhere.

      It’s probably stated somewhere really obvious, and I’m just overlooking it? I don’t know.

Bad questions

  • What are the nix equivalents of nix-env, nix-build, and nix-instantiate?

    • My overall impression is that the nix binary, at least right now, has a couple of really useful commands (nix search, nix repl) and a couple of pretty-useful commands (nix show-config, nix show-derivation) and then dozens of random little utility things that you’ll never need that should be hidden behind some subcommand but aren’t.

      There are actually 31 subcommands of the nix binary. There is no hierarchy to these commands; nothing that makes them browseable. Some examples:

      to-base16        convert a hash to base-16 representation
      to-base32        convert a hash to base-32 representation
      to-base64        convert a hash to base-64 representation
      to-sri           convert a hash to SRI representation
      

      These commands exist at the same level as, say, nix repl, despite one of those things being vastly more commonplace.

      I quickly gave up on trying to use nix, or looking for nix-equivalents of commands. I stopped wanting that: I stopped caring about the nix command, a few chapters into the manual. It proved that it was not the usability overhaul I was hoping for, and I embraced the “old-style” nix-foo commands.

      So while there is a nix build command, I haven’t used it: I tried it once, but it didn’t work as well as nix-build, so now I am soured to it forever. I know there’s no equivalent of nix-env, and I would be very surprised if there’s a nix-instantiate equivalent.

  • What is the nix equivalent of nix-store -qR to print out the closure of a store path?

    • I don’t know, but again, I don’t really care: I expect there isn’t one. Maybe nix path-info can do this, but if so it isn’t documented.
  • What are the nix equivalents of nix-store --dump and nix-store --restore, for working with NARs?

    • I don’t know, and I don’t really care.
  • Why is there no man nix?

    • Because there isn’t?
  • Why did nix-env -i hello tell me it “created 40 symlinks in user environment”?

    • I get what this means now, but I think the message is useless and confusing. This is basically a debug-level log message.
  • How do I install commands using nix instead of nix-env?

    • I don’t.
  • Why does nix run need the nixpkgs qualifier when nix-shell doesn’t?

    • It’s pretty much a complete mystery to me what commands will accept what arguments. nix-env takes package names, except when it doesn’t; nix-shell -p evaluates arbitrary Nix expressions with the nixpkgs entry on your NIX_PATH in scope, but nix-shell takes a path – a Nix path, not a file path – and on and on. So I don’t know. Because every command is a special snowflake.
  • Why is there an --upgrade command if --install will upgrade packages?

    • This is dumb and --upgrade is dumb and you should never use it.
  • How do I pretty print Nix files?

    • As far as I can tell, there is no built-in way to do this. I managed to do this with a third-party tool called nixpkgs.nixfmt, but it wants to reformat files in-place, which is not very useful.
  • Why do hashes appear at the beginning of store paths instead of the end?

    • I dunno, because whatever? This seems natural to me, despite it making tab-completion harder.
  • What are the sizes of integral and floating point numbers?

    • According to builtins.valueSize, they are both 64-bits, but I don’t know if that’s just because it’s the native size. I don’t actually care at all, though: if this ever matters to me, something has gone horribly wrong.
  • Why does mkDerivation pass through args literally?

    • I would call this a bug, but in practice you don’t ever pass positional arguments to your builder, you just pass environment variables, so it doesn’t really matter.
  • What is the use case for nix-env --set?

    • Don’t know; don’t care.
  • Why can’t I say nix-env -eA nixpkgs.hello? Why do I need to use the “symbolic name”?

    • Ehhh yeah I mean because package names are dumb and the user environment doesn’t remember the path you used to install packages.
  • How do I pretty print Nix expressions?

    • Duplicate; see above.
  • Why don’t I have man pages for coreutils?

    • Requires coreutils-full; this is probably a disk space thing? I found it extremely confusing, but whatever.

      A comment in the derivation seems to support this:

      $ grep man1 -B1 -A5 ~/src/nixpkgs/pkgs/tools/misc/coreutils/default.nix
      
        postInstall = optionalString (stdenv.hostPlatform != stdenv.buildPlatform && !minimal) ''
          rm $out/share/man/man1/*
          cp ${buildPackages.coreutils-full}/share/man/man1/* $out/share/man/man1
        ''
        # du: 8.7 M locale + 0.4 M man pages
        + optionalString minimal ''
          rm -r "$out/share"
        '';
      

      (minimal = false in coreutils-full.)

  • Why do I have to explicitly install info pages for coreutils?

    • Because no one wants info pages. I only asked this because I couldn’t find the man pages, but then I did, so this question doesn’t really matter.
  • Why doesn’t overrideAttrs just transform a set into a new set?

    • Slight convenience with relatively low cost?
  • Why doesn’t nix-collect-garbage --dry-run do the thing I expect?

    • I dunno, because it would be more work?
  • What derivation attributes are special enough that nix repl prints them out?

  • Why is prefer-remote-fetch kebab-cased?

    • There are lots of functions like this in Nixpkgs. I don’t know, but I’m guessing because the files are kebab-cased, and fixing these would cause a lot of breakage.
  • Is it safe to get rid of locateDominatingFile (and other unused lib functions)?

    • Ehh, maybe; I don’t really care.
  • Why is lib.misc not called lib.deprecated?

    • I can safely assume backwards compatibility with a historical accident.
  • Why is lib.trivial not called lib.misc?

    • I can safely assume backwards compatibility with a historical accident.
  • Do we need fetchFromSavannah here?

    • I think the answer is no, but, like, also, who cares.
  • Why does the repl instantiate .drv files and put them into the actual store?

    • Like many “why” questions, I doubt I’ll get a real answer here, and don’t really care enough to try to track it down.

Questions without answers, even in this day and age

  • What does it mean to compose a package?
  • What is NIX_PROFILES?
  • What are all those /nix/store/...user-environment/share/nix/*.nix files?
  • Why does the default install give me https://nixos.org/channels/nixpkgs-unstable which 302s to https://channels.nixos.org/nixpkgs-unstable?
  • Why is the store object in ~/.nix-defexpr also called a user-environment?
  • Can I put a space in a Nix package name?
  • How do “special” paths like stdenv-darwin wind up in the store / stay in the store? Are those part of the nix package?
  • Why is there a Commander Keen game in nixpkgs? How is that allowed?
    • I’ll leave this one as an exercise for the reader. It’s easy to look into; I looked into it; I have no further questions. Everything checks out.
  • What is $hostOffset in a setup hook?
  • How do I actually find the logs I want in /nix/var/log/nix?
  • How do extended file system attributes work in Nix?
  • Why doesn’t fetchGit return a fixed-output derivation?
  • What is builtins.placeholder?
  • What is “context”?
  • What do the unsafe functions do?
  • What is scopedImport?
  • Is there any difference between nix-build and nix build?
  • What’s up with that weird array situation?
  • What’s the “user environment build script”
  • Why does nix eval need its argument to be in parentheses?
  • Why doesn’t nix-store --read-log work?
  • What does allow-import-from-derivation do?
  • How can I set up my own “hashed mirror?”
  • How should I install my login shell with Nix?
  • How do I --keep-failed with nix build?
    • I think maybe nix log has something to say here?
  • What’s the difference between nix build and nix-build?
    • Duplicate.
  • What is the not terribly gross way to run nix-shell -p with a package from a custom channel (i.e. without renaming it to "nixpkgs")?
  • Can I run Nix tests after nix-build without doing a full rebuild from nix-shell?
  • In the case that I have multiple substituters configured, how can I see which substituters have certain packages?
  • How do I see what (package × architecture) pairs are supposed to be cached in the official cache?
  • How do I quickly “go to definition” of a package?
  • What on earth is builtins.placeholder for?
    • Duplicate.
  • How can I use overrideAttrs to remove an attribute?
  • How do I print the contents of a derivation without setting the type to something else?
  • What’s up with lib.strings.addContextFrom?
  • What’s with fix' and the __unfix__ attribute? Should I care about this?
  • What is hydra-eval-jobs?
  • Where is lib.warn defined?
  • What… on earth… is all of this platform arithmetic? What do these numbers mean? Why– what is happening here?
  • Why does the substituteAll builder need to call preInstall/postInstall?
  • Is it true that “Environment variables are then substituted in it using substituteAll”? Is Python doing that explicitly unnecessarily, or are the docs wrong?
  • Why is there a stdenv.targetPlatform? What does that mean?
  • How can I get ldd on my macOS box?
  • Why did Nix try to install Xcode to build hello for macOS?
  • Why is install_name an intrinsic property of a .dylib file?
  • What does it mean to “have a builder for the system” of runCommandLocal?
  • Does allowSubstitues = false disable substitutes for all dependencies of a derivation as well?
  • What is runtimeShell, and when should I prefer it over $SHELL?
  • How can I nix search through nixpkgs.nodePackages?
    • Oddly, I can search through nixpkgs.ocamlPackages
  • How am I supposed to use e.g. bower2nix while iterating on a package from nix-shell?
  • What the heck is up with the Node.js stuff?
  • How do hashed-mirrors work?
  • Why does Nix… disable TLS when fetching sources? What?
  • How do I enable the sandbox for a single build?
  • Is there anything Nix-specific about NAR files?

So… now what? Do I go through and try to answer every single one of these?

No. Of course not. This post has taken way too long already. None of these questions are really pressing, and I can find the answers in my own time, as I do more real Nix things. I already closed like 65% of my open questions in this post; I can leave the rest for later.


  1. You might be wondering: why is that in there?

    Basically, without an explicit MANPATH, man is going to look through elements in your PATH, and try to find a “nearby” man/ directory for each entry. If it finds one, it adds it to the MANPATH.

    A concrete example: if you have /foo/bar/baz/bin on your PATH, it’s going to look for ../share/man – i.e., /foo/bar/baz/share/man. If it finds it, it adds it to the manual search path. And then it stops.

    If it doesn’t find ../share/man, it will then look for ../man. So if you only had a ~/.nix-profile/man directory and no ~/.nix-profile/share/man directory, then man would work as expected. But if you then grew a ~/.nix-profile/share/man directory, man would no longer be able to find the ~/.nix-profile/man directory, because every PATH entry only gets a single corresponding MANPATH entry.

    This behavior is not documented anywhere, at least in the man that macOS ships. The most it has to say about it is:

    […] for each directory in the command search path (we’ll call it a “command directory”) for which you do not have a MANPATH_MAP statement, man automatically looks for a manual page directory “nearby” namely as a subdirectory in the command directory itself or in the parent directory of the command directory.

    You can disable the automatic “nearby” searches by including a NOAUTOPATH statement in /private/etc/man.conf.

    That says nothing about the ../share/man behavior, which is the salient thing here. But you can check the implementation of the find_man_subdir function in manpath.c, if you want a better answer.

    That is hilarious, isn’t it? I find running man man very funny, and the fact that it doesn’t actually document the one bit of behavior I’m curious about even funnier. Computers are great.

    Out of curiosity: does GNU man fare better?

    I run nix-shell -p man-db to check. Experimenting with manpath reveals that it will add both ../share/man and ../man if they exist, unlike macOS’s man. But neither man man nor man manpath has any information about why this is or where those values come from, and even the man.conf file shipped doesn’t include a note about it (my /etc/man.conf at least hints at this behavior, by telling you how to disable it).

    In fact the only reference to this behavior that I can find is a comment in the source: see get_manpath_from_path in manp.c.

    Anyway this is the longest footnote I have ever written how are you doing. ↩︎