Many things to love about Nix flakes so far. But one major source of frustration we’ve been running into adopting is using multiple flakes in the same repo. The architecture I had in mind is:
- a root flake with the master development shell for a monorepo
- a bunch of flakes sprinkled in folders that inherit the root flake (or even inherit something that inherits from root shell) and adds whatever that specific monorepo folder requires.
The way I accomplished that, briefly is:
./flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/release-23.05";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in rec {
devShells.base = pkgs.mkShellNoCC {
packages = with pkgs; [
# ...
];
};
});
}
./some-folder/flake.nix
{
description = "Neuralink infrastructure-specific flake";
inputs = {
sw.url = "path:../";
nixpkgs.follows = "sw/nixpkgs";
flake-utils.follows = "sw/flake-utils";
};
outputs = { self, nixpkgs, flake-utils, sw, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
swShells = sw.devShells.${system};
swPackages = sw.packages.${system};
swOverlays = sw.overlays.${system};
in rec {
devShells.default = pkgs.mkShellNoCC {
packages = with pkgs;
[
# ...
];
inputsFrom = [swShells.default];
};
});
}
There might be some typos redacting these down to the bare essentials, but this generally works. However, the recurring issue seems to be that the narHash
in the flake.lock
in the sub-folder will change:
- whenever the root flake changes (fine)
- between developer machines? (not fine)
This is what the lock stanza looks like:
"sw": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 0,
"narHash": "sha256-AoVnviwh3Fx0wjd1bBMzFPiHL/xqgmDrTfFyI3860pU=",
"path": "../",
"type": "path"
},
"original": {
"path": "../",
"type": "path"
}
},
Same git commit, clean repo, two people on two different darwin_aarch64 machines get different narHash. The failure case here looks like this:
$ nix develop
path '<REDACTED>' does not contain a 'flake.nix', searching up
error:
… in the condition of the assert statement
at «string»:66:13:
65| if node.flake or true then
66| assert builtins.isFunction flake.outputs;
| ^
67| result
… while calling the 'isFunction' builtin
at «string»:66:20:
65| if node.flake or true then
66| assert builtins.isFunction flake.outputs;
| ^
67| result
(stack trace truncated; use '--show-trace' to show the full trace)
error: cannot fetch input 'path:../?lastModified=0&narHash=sha256-JdMWfTmMQpwVag%2B/lhwEFI9NgYykJnDkKdpr93G4Guo%3D' because it uses a relative path
What am I missing here? Given that nix searches up for the nearest flake, this design should almost be the encouraged pattern. I did try git+file
but that had other issues I can get into, if that’s the path we should be following here.