This question is really specific to my way of doing things but I think it can be enlightening to ask here for visibility on the (I hope there is one) solution and the understanding of the inner workings.
The setup
To work on my NixOS setup I have the following tree hierarchy in the root of my configuration directory :
.
├── dotfiles
├── lib
├── machines
├── modules
├── overlays
├── packages
├── pkgs
├── secrets
└── sources
In the modules
directory, I have file default.nix
that looks like this :
{ lib, config, pkgs, ... }:
with lib; with builtins; with types;
let
# Recursively constructs an attrset of a given folder, recursing on directories, value of attrs is the filetype
getDir = dir:
mapAttrs
(file: type: if type == "directory" then getDir "${dir}/${file}" else type)
(readDir dir);
# Collects all files of a directory as a list of strings of paths
files = dir:
collect isString
(mapAttrsRecursive (path: type: concatStringsSep "/" path) (getDir dir));
# Filters out directories that don't end with .nix or are this file, also makes the strings absolute
validFiles = dir:
map (file: ./. + "/${file}")
(filter (file: hasSuffix ".nix" file && file != "default.nix" && !hasSuffix "lib.nix" file) (files dir));
overlays = (import ../overlays/overlays.nix { inherit lib; }).overlays;
src-location = (import ../sources { inherit lib; inherit (pkgs) callPackage; });
in
{
imports = validFiles ./.; # <= HERE
config.nix.nixPath = [
"/nix/var/nix/profiles/per-user/root/channels"
"nixos-config=/etc/nixos/configuration.nix"
] ++ (lib.attrsets.mapAttrsToList (name: value: "${name}=${value}")) src-location;
config.nixpkgs.overlays = overlays;
}
This file allows me to organize my files in the module directory how I please (at least that’s what I thought) and let NixOS to do the import and evaluation thanks to imports marked “HERE”.
For a machine configuration in a subdirectory of the machine
directory I have for example
{ lib, config, pkgs, ... }: {
imports = [
<nixos-hardware/raspberry-pi/2>
<nixpkgs/nixos/modules/profiles/minimal.nix>
../../modules # The infamous import of the above file here
];
networking.hostName = "ophion";
# Personal modules defined throughout the `module` directories
perso = {
ssh = true;
rust-utils = true;
type = "server";
services = {
cluster = {
enable = true;
role = "server";
};
};
};
# NixOS defined module
boot.cleanTmpDir = true;
}
It might not be the best and most efficient solution (I am more than interested in improvements so please comment ahead if you have any!) but it works well enough for my use case until…
The problem
I am in the process of setting up a Raspberry Pi from an x86_64 machine using nixos-generators to build the ISO image. When I pass the configuration file (the one above) with nixos-generate -f iso -c machines/ophion/default.nix
, I get
error: path '/nix/store/qyinilkg5l70jp87mnvq9ncgg8hmbiw7-modules' is not valid
A keen eye will have noticed that this is one of the path from my configuration. Although this specific store path does not exist, many others (created by nixos-rebuild
, I imagine) do exist and contain the content of the modules directory at the time of execution of nixos-rebuild
.
The same configuration can be built without an issue by nixos-rebuild
.