Good Afternoon,
I’m working on modularising my nixos configuration, but I’m running into some problems when performing my imports. I’d like to do something like this:
{config, pkgs, lib, ...}:
let
components = with .../components/general; [
/base-config.nix
/graphical.nix
/networking.nix
/sound.nix
/bluetooth.nix
/printing.nix
];
programs = with .../programs; [
/core.nix
/cad.nix
/devkit.nix
/gaming.nix
];
users = with .../users; [
/$user.nix
];
in
{
imports = components ++ programs ++users;
}
All the file paths are correct, but the with statements are not working with file paths, so I assume I’m doing this the wrong way. Is there a correct way to do this other than typing out the full path for each file manually?
Thanks.
Add a default.nix to the folder an there import your modules.
configuration.nix
{
imports = [ ./components ./programs ./users ];
}
./components/default.nix
{
imports = [
./base-config.nix
./graphical.nix
./networking.nix
./sound.nix
./bluetooth.nix
./printing.nix
];
}
with keyword exposes an attr, ie:
let
programsPaths = {
core = ./programs/core.nix;
cad = ./programs/cad.nix;
};
programs = with programsPaths; [ core cad ];
in
{
imports = programs ++ compontens ++ users;
};
Would be easier just add paths without with
You could use let after equals and concat vars
let
components = let p = ../components/general; in [
(p + "/base-config.nix")
(p + "/graphical.nix")
];
in
{
imports = components ++ programs ++users;
}
I would prefer default.nix version 
In your example has ... in nix parent dir is ../, current dir is ./.
There is also Haumea. to convert your dir structure in options. But to your case would be too complex.
2 Likes
I’m bumping this old thread as I don’t think that is has an entirely satisfactory solution.
I was looking to have any file I added to my modules folder automatically imported without needing to edit my config or the default.nix in the modules directory. That way I can just add a line to my configs enabling the modules I want on a given system without worrying about if they are imported or not.
My version requires enabling the experimental pipe-operators feature, you could write a longer version that doesn’t need it but its harder to understand and more verbose.
{ config, pkgs, lib, ... }:
let
b = builtins; # short alias for builtins
module_files = ../modules/ |> # assign the result of the pipe to module_files, & pass ../modules/ to the function on the next line
b.readDir |> # returns an attribute set, names are files, values their type
b.attrNames |> # gets the names of the attribute set, the files
b.filter (f: lib.strings.hasSuffix ".nix" f) |> # keep only files that end in ".nix"
b.map (e: ../modules/${e}); # for each file prepend the path to the directory
in
{
imports = module_files
}
I’m still not very good at nix lang so I couldn’t figure out how not to have to repeat the path to the modules folder in the first step and the map. Saving it to a variable didn’t seem to work - something about the way paths are handled being different from strings maybe IDK. If someone knows how to have the module path as a variable I’d appreciate it.
1 Like