Nix: Import from a trivial derivation needlessly requires network access (which will fail to fetch anyways)

Created on 9 Nov 2018  Â·  11Comments  Â·  Source: NixOS/nix

Example:

test.nix:

let

  inherit (import <nixpkgs> {}) runCommand;

  drv = runCommand "test" {} ''
    echo "{}" > $out
  '';

in import "${drv}"

Now, turn off network and run:

$ nix-instantiate -v test.nix

[…]

evaluating file '/nix/store/dyilzxs9z1kbrbmwjkl9869s440sq81v-nixos-18.03/nixos/pkgs/stdenv/common-path.nix'
querying info about '/nix/store/bzq000c18inh7bsnzmwrv8pzvfa11j4f-offline-ifd-test' on 'https://cache.nixos.org'...
downloading 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo'...
warning: unable to download 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo': Couldn't resolve hosts
warning: unable to download 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo': Couldn't resolve hosts
warning: unable to download 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo': Couldn't resolve hosts
warning: unable to download 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo': Couldn't resolve hosts
warning: unable to download 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo': Couldn't resolve hosts
warning: unable to download 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo': Couldn't resolve hosts
warning: unable to download 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo': Couldn't resolve hosts
error: unable to download 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo': Couldn't resolve host n)

Re-run with network connectivity:

$ nix-instantiate -v test.nix

[…]

evaluating file '/nix/store/dyilzxs9z1kbrbmwjkl9869s440sq81v-nixos-18.03/nixos/pkgs/stdenv/common-path.nix'
querying info about '/nix/store/bzq000c18inh7bsnzmwrv8pzvfa11j4f-offline-ifd-test' on 'https://cache.nixos.org'...
downloading 'https://cache.nixos.org/bzq000c18inh7bsnzmwrv8pzvfa11j4f.narinfo'...
building '/nix/store/8a5gmhd3pjyg5k5fwc4mwvj70a9z1aar-offline-ifd-test.drv'...
linking '/nix/store/bzq000c18inh7bsnzmwrv8pzvfa11j4f-offline-ifd-test' to '/nix/store/.links/1xyw8jzhbh0aiivnm376ld01'
evaluating file '/nix/store/bzq000c18inh7bsnzmwrv8pzvfa11j4f-offline-ifd-test'

/cc @vcunat @shlevy @domenkozar

This also breaks offline nixpkgs.dhallToNix, even if nixpkgs.dhall-nix is in local store, and it’s how I encountered this. /cc @Gabriel439

Most helpful comment

@Gabriel439 very close. You actually need to set allowSubstitutes = false; while preferLocalBuild will substitute if one exists, but prevent distributed builds to happen. See https://github.com/NixOS/nix/commit/1109193ea3a25208d438c65b2d79e207ae1af039

Using trivial derivations you need to set both to true.

All 11 comments

So even if the derivation can be built locally, and I’m somewhere wild without range, I’m doomed. Seems… wrong.

Have you tried to pass the option

--option 'binary-caches' ''

?

Should work with it without network access.

@michalrus: Perhaps this would work:

runCommand "test" { preferLocalBuild = true; } ...

What I believe is happening here is that in the absence of preferLocalBuild = true Nix has an obligation to check all available substituters (i.e. caches that you have registered such as cache.nixos.org) to see if this derivation may have already been built before. Adding preferLocalBuild = true tells Nix to not bother to check caches. In fact, if you browse the trivial builders here:

https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/trivial-builders.nix

... you will find many builders derived from runCommand that set preferLocalBuild, too, typically for derivations where it is cheaper to rebuild it locally than to fetch it from a cache.

@Gabriel439 very close. You actually need to set allowSubstitutes = false; while preferLocalBuild will substitute if one exists, but prevent distributed builds to happen. See https://github.com/NixOS/nix/commit/1109193ea3a25208d438c65b2d79e207ae1af039

Using trivial derivations you need to set both to true.

Ohhhhhhhhh. Very cool! Thank you, both! :sparkles:

@Gabriel439 so perhaps this dhallToNix expression should use allowSubstitutes = false;?

Glad that resolves your question :)

@michalrus: Yeah, dhallToNix should probably set both preferLocalBuild = true; and allowSubstitutes = false;

E.g. like

{
  dhallToNix = code:
    let

      drv = runCommand "dhall-compiled.nix" {
        inherit code;
        passAsFile = [ "code" ];
        preferLocalBuild = true;
        allowSubstitutes = false;
        buildInputs = [ dhall-nix ];
      } ''
        dhall-to-nix <<< $codePath > $out
      '';

    in
      import drv.outPath;
}

A derivation can be marked as trivial and unnecessary to substitute by adding allowSubstitutes = false; to the attributes. That will disable substitutes for that specific derivation without having to disable it on the cli.

EDIT: looks like I had an old tab open 😄

@michalrus: Yeah, that looks correct to me

If these options were designed anew, I'd suggest that preferLocalBuild = true by default implies allowSubstitutes = false (possibly naming these differently). If a build feels simple enough not to delegate to another machine, it's _probably_ not worth substituting either.

EDIT: let me provide an example where it _is_ worth it: when a "build" is trivial to compute from inputs, but build-time closure is significantly larger than run-time closure. There the substitution may help noticeably, depending on current nix store contents.

Now it would be an incompatible change at nix level, so it's probably not worth it. Introducing a new name implying both also doesn't seem worth it at this point.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bryanhuntesl picture bryanhuntesl  Â·  3Comments

Infinisil picture Infinisil  Â·  3Comments

drewm1980 picture drewm1980  Â·  3Comments

chexxor picture chexxor  Â·  4Comments

copumpkin picture copumpkin  Â·  3Comments