A set of Nix functions/modules to ease the creation of sharable, flexible and standardized Nixos configurations.
You may find a complete working example in the crocuda module repository.
Where all the magic happens in default.nix
.
-> crocuda.nixos.
Merge a nixOs module and its home-manager equivalent module in a single module. Internaly uses home-manager.
When using home-manager you can find yourself with an unflexible configuration that can't be shared without substential rewritting efforts because:
-
You can get away with hardcoded user names (and some other variables).
users.users.<username> = { some_stuffs = {}; }
-
For a same program, you have to import standard modules and home-manager modules separately, resulting in file duplication and awkward dependency management.
. ├── nixos │ ├── gnome.nix │ └── hyprland.nix └── home-manager ├── gnome.nix #should be grouped with its homologous. └── hyprland.nix
and unwelcoming top-level module declaration.
# flake.nix nixosConfiguration = { default = pkgs.lib.nixosSystem { inherit system; modules = [ ./nixos/gnome.nix home-manager.nixosModules.home-manager { home-manager.users.<username> = {pkgs,...}: { imports = [ ./home-manager/gnome.nix ]; }; }; ]; }; };
To circumvent this issues, you may want to either make your own functions, ditch home-manager (pretty radical), or simply use the home-merger module.
-
This results in tidy filetrees, with separation of concerns.
. ├── gnome │ ├── default.nix │ └── home.nix └── hyprland ├── default.nix └── home.nix
-
And friendly top-level module declaration.
You then only need to import one file for both standard module and home-manager module.
# flake.nix nixosConfiguration = { default = pkgs.lib.nixosSystem { inherit system; modules = [ ./gnome/default.nix ./hyprland/default.nix ]; }; };
The magic happens in the standard module file (here default.nix
).
You can import a home-manager modules through home-merger.
# default.nix
home-merger = {
# A list of users username for which to apply the modules.
users = ["alice", "bob"];
# Arguments to pass to the module
extraSpecialArgs = { inherit inputs cfg; };
# A list of modules to be applied to the users
modules = [
./home.nix
];
}
Calling home-manager directly would raise an error because you can only declare the home-manager module once.
The home-merger function simply aggregates every home-manager nixosModules to declare them at once.
It is just a 60 lines function but oh boy does it do good!
Time to glow by your nix aptitudes.
You may want to declare your users only once at the top-level of your configuration.
Just create a global variable.
# flake.nix
options = with lib; {
my_config = {
users = mkOption {
type = with types; listOf str;
default = [];
example = literalExpression "[\"alice\",\"bob\"]";
description = ''
The name of users to apply modules to.
'';
};
};
};
config.my_config.users = ["anon"];
And use it as an argument value in home-merger.
# default.nix
home-merger = {
users = config.my_config.users;
extraSpecialArgs = { inherit inputs; };
modules = [
./home.nix
];
}
Head to the template directory for a boilerplate -> example.
Now a way to get rid of all this boilerplate of import statements, is to use a top-level umport.
imports = inputs.nixos-tidy.umport {
# User specific
paths = [./my_module];
};
home-merger = {
users = my_config.users;
modules = inputs.nixos-tidy.umport-home {
paths = [./my_module];
};
};
Every files of this-file tree will be recursively imported without the need of import statements.
.
├── gnome
│ ├── default.nix
│ └── home.nix
├── hyprland
│ ├── default.nix
│ └── home.nix
└── default.nix #put boilerplate code at the top-level.
Cherry pick the unfree software you want to allow with regexes.
You can either allow every unfree software, or you must set it per package. This can become very anoying when facing big dependency trees like with printers, scanners, graphics cards,... you know the drill.
#default.nix
config.allowUnfree = true;
# or
config.allowUnfreePredicate = [
"package_name"
"other_similar_package_name"
"on_and_on"
];
Fortunately some packages have the same prefixe in their names (nvidia_this, nvidia_that,...) Through the allow-unfree function you can define the package to allow with regexes.
#default.nix
allow-unfree = [
# use regexes
"nvidia-.*"
"cuda.*"
];
Add the flake to your existing configuration.
# flake.nix
{
description = "My NixOS flake";
inputs = {
nixos-tidy.url = "github:pipelight/nixos-tidy";
};
outputs = {
self,
nixpkgs,
...
} @ inputs: {
nixosConfiguration = {
default = pkgs.lib.nixosSystem {
specialArgs = {inherit inputs;};
modules = [
inputs.nixos-tidy.nixosModules.home-merger;
inputs.nixos-tidy.nixosModules.allow-unfree;
./default.nix
];
};
}
};
}