Skip to content

Flakes in the nix store do not retain references to their inputs #6895

@tejing1

Description

@tejing1

Describe the bug

Many nixos + flakes users keep a reference to self in their nixos generations, for traceability, however this does not ensure that inputs to the flake are kept in the closure. For most inputs, in most cases, this simply means they need to be re-downloaded from github or wherever they came from, however for path: inputs, and for inputs where the source has been taken down for some reason, a user may be unpleasantly surprised to find that they do not, in fact, have all the nix code needed to reproduce their system.

Steps To Reproduce
(Note the dependence on PWD in flake2's inputs. Adjust as needed if reproducing.)

$ find
.
./flake2
./flake2/flake.nix
./flake1
./flake1/flake.nix
$ cat flake1/flake.nix
{
  outputs = { self, ... }: {
    foo = 1;
  };
}
$ cat flake2/flake.nix
{
  inputs.nixpkgs.url = github:nixos/nixpkgs/nixos-22.05;
  inputs.flake1.url = path:/mnt/persist/share/data/tejing/work/tmp/flake1;
  outputs = {self, nixpkgs, flake1}: {
    inherit (flake1) foo;
    result = nixpkgs.legacyPackages.x86_64-linux.runCommand "flake2-result" { inherit (self) outPath; } ''
      mkdir $out
      ln -s $outPath $out/self
    '';
  };
}
$ nix eval ./flake2\#foo
warning: creating lock file '/mnt/persist/share/data/tejing/work/tmp/flake2/flake.lock'
1
$ nix build ./flake2\#result
$ nix eval $(realpath ./result/self)\#foo
1
$ mv flake1 flake1.bak
$ nix-store --gc
finding garbage collector roots...
deleting garbage...
deleting '/nix/store/8igg0ivjv0y8c04ac7b78n0zgmg1i987-source'
... SNIP ...
deleting '/nix/store/wj6j8lrdlind44n7vqn864ga7y802vc7-libunistring-1.0'
deleting unused links...
note: currently hard linking saves 4783.59 MiB
32 store paths deleted, 73.96 MiB freed
$ nix eval $(realpath ./result/self)\#foo
error (ignored): error: end of string reached
error: getting status of '/mnt/persist/share/data/tejing/work/tmp/flake1': No such file or directory
(use '--show-trace' to show detailed location information)

Expected behavior

I would expect that final nix eval $(realpath ./result/self)\#foo to successfully produce 1, just as it did before the gc, indicating that saving self in the result output had in fact kept everything necessary to re-evaluate the flake.

nix-env --version output

$ nix-env --version
nix-env (Nix) 2.8.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions