Moving module into configuraton.nix

I’m trying to move display-manager.nix module into configuration.nix and 3 variables into flake.nix

Here is display manager module:

{ pkgs, ... }:

# Enable Display Manager.
let
  tuigreet = "${pkgs.greetd.tuigreet}/bin/tuigreet";
  session = "${pkgs.hyprland}/bin/Hyprland";
  username = "mee";
in
{
  services.greetd = {
    enable = true;
    settings = {
      initial_session = {
        command = "${session}";
        user = "${username}";
      };
      default_session = {
        command = "${tuigreet} --greeting 'Welcome to NixOS' --asterisks --remember --remember-user-session --time --cmd ${session}";
        user = "greeter";
      };
    };
  };
}

configuration.nix:

{ Variables, pkgs, ... }:

{
  # Enable Flakes.
  nix.settings.experimental-features = [ "nix-command" "flakes" ];

  # Display manager.
  services.greetd = {
    enable = true;
    settings = {
      initial_session = {
        command = "${Variables.session}";
        user = "${Variables.username}";
      };
      default_session = {
        command = "${Variables.tuigreet} --greeting 'Welcome to NixOS' --asterisks --remember --remember-user-session --time --cmd ${Variables.session}";
        user = "greeter";
      };
    };
  };
}

and flake.nix:

{
  description = "Configurations";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";
    nixpkgs-stable.url = "nixpkgs/nixos-23.11";
    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };
  outputs = { nixpkgs, nixpkgs-stable, home-manager, ... }:
    let
      Variables = {
        username    = "mee";
        hostname    = "nixos";
        system      = "x86_64-linux";
        lib         = nixpkgs.lib;
        pkgs        = nixpkgs.legacyPackages.${Variables.system};
        pkgs-stable = nixpkgs-stable.legacyPackages.${Variables.system};
        tuigreet    = "${pkgs.greetd.tuigreet}/bin/tuigreet";
        session     = "${pkgs.hyprland}/bin/Hyprland";
      };
    in
    {
      nixosConfigurations = {
        nixos = Variables.lib.nixosSystem {
          system = Variables.system;
          specialArgs = { inherit Variables; };
          modules = [
            ./configuration.nix
            ./hardware-configuration.nix
          ];
        };
      };
      homeConfigurations = {
        mee = home-manager.lib.homeManagerConfiguration {
          pkgs = Variables.pkgs;
          extraSpecialArgs = { inherit Variables; };
          modules = [
            ./home.nix
            ./modules/home/xdg.nix
            ./modules/home/gtk.nix
          ];
        };
      };
    };
}

It complain in flake.nix about undefined variable ‘pkgs’ on tuigreet line.

I think you want a rec in front of your Variable set. But to be honest I don’t really get the point of your complicated construction with Variables.

Do you mean to use rec instead of let in?

I did use Variables to simplify some stuff, but maybe there is a better way to do it. I don’t need that way to inherit in flake.nix 10 or more variables and instead I have one ‘inherit Variables’ in specialArgs and in extraSpecialArgs to all modules. Also in other modules I don’t need to specify 10+ attributes and use mostly one ‘Variables’. Maybe it’s a newbie way, but I don’t know any better way. :smiley:

No, I mean:

let
      Variables = rec { # <--- see the rec added here?
        username    = "mee";
        …
      };

This allows set values to be defined based on other set attributes. Demo:

$ nix repl
nix-repl> {a=4; b=a;}     
error: undefined variable 'a'

       at «string»:1:9:

            1| {a=4; b=a;}
             |         ^

nix-repl> rec {a=4; b=a;}
{ a = 4; b = 4; }

Ok then it might be good, I don’t know exactly your case, it might be perfectly fine to use it.

It’s just that I feel like you have quite a lot of variable, and that you might be able to replace them advantageously with module. For instance, once you know pkgs, you directly have lib = pkgs.lib, system = pkgs.system so what you do seems like unnecessary redundancy, and lib (and I think system as well) are even part of the input of the modules, so you can do:

{pkgs, lib, ...}:
{
   lib.foo
}

instead of

{pkgs, Variable, ...}:
{
  Variable.lib.foo
}

which has also the advantage of being more standard. Similarly, I’m not sure why you need tuigreet to be in a new variable. Are you using it in many places? Because your list of variables might get quite cluttered if you put any single thing there.

I would say that a really “clean” way would be to use a module instead, as modules are first quite standard, allows you more advanced use cases (e.g. you get typing, default values, computed values, documentation, you can raise error if a set of configuration is not “legal” etc), they are easier to reuse and composes nicely (you can reuse your module inside any other configuration, typically with a single line, change selectively some values etc). If needed, you can also share your module between homeConfiguration and nixosConfiguration importing it in both modules = [ ./mymodule.nix ];.

For instance, you can create a file mymodule.nix with something like:

{pkgs, lib, config, ...}:
{
  # We create new options that can be configured later.
  options.myModule = {
    # If you want you can also add an option "enable" to be allowed to selectively enable your module
    # See https://nixos.wiki/wiki/NixOS_modules for an example
    mainUser = mkOption {
      type = str;
      default = "Bob";
    };
  };
  # This code could be put in any other module, like in `configuration.nix`, just make sure to have "config"
  # added in the input. Use `config.myModule.mainUser` instead of `Variable.mainUser` to get the value.
  config = {
    users.users.${config.myModule.mainUser} = {
      isNormalUser = true;
    };
    # You can also change/set option value with:
    # myModule.mainUser = "Alice";
    # Since lists are merged automatically, this can be handy to define one option from multiple place.
  };
}

But I don’t know, it might be over engineered for your use case, you are the only judge here, I just find it more standard, reusable, customizable (e.g. maybe in homeConfiguration you will want to add one element to some lists… and then it will be harder to do that).

1 Like

Thank you very much for your exhaustive answer.

Inspired by XNM1, my entire configuration.nix was chopped into 20-30 modules. Then I realized, that I want almost everything back while keeping some variables in one place. Display-manager module was the last one causing error.
.

“This allows set values to be defined based on other set attributes.”

That is quite weird, because pkgs and pkgs-stable are already using variables based on other specified variables, but not tuigreet and session.

pkgs = nixpkgs.legacyPackages.${Variables.system};
pkgs-stable = nixpkgs-stable.legacyPackages.${Variables.system};
tuigreet = "${pkgs.greetd.tuigreet}/bin/tuigreet";
session = "${pkgs.hyprland}/bin/Hyprland";

Lib I had from here. Before there was some problem about unfree packages, so I kept lib for a while. Tried to set things like in his video for unstable packages and I had more problems. Now after some changes, maybe removal of lib variable and ‘system = Variable.system’ it’s working fine even without rec:

pkgs = nixpkgs.legacyPackages.${Variables.system};
pkgs-stable = nixpkgs-stable.legacyPackages.${Variables.system};
tuigreet = "${Variables.pkgs.greetd.tuigreet}/bin/tuigreet";
session = "${Variables.pkgs.hyprland}/bin/Hyprland";

With rec it looks cleaner, so my config now looks something like this:

{
  description = "Configurations";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";
    nixpkgs-stable.url = "nixpkgs/nixos-23.11";
    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { nixpkgs, nixpkgs-stable, home-manager, ... }:

    let
      Variables = rec {
        username    = "mee";
        hostname    = "nixos";
        system      = "x86_64-linux";
        pkgs        = nixpkgs.legacyPackages.${system};
        pkgs-stable = nixpkgs-stable.legacyPackages.${system};
        tuigreet    = "${pkgs.greetd.tuigreet}/bin/tuigreet";
        session     = "${pkgs.hyprland}/bin/Hyprland";
      };
    in
    {
      nixosConfigurations = {
        nixos = nixpkgs.lib.nixosSystem {
          specialArgs = { inherit Variables; };
          modules = [
            ./configuration.nix
            ./hardware-configuration.nix
          ];
        };
      };
      homeConfigurations = {
        mee = home-manager.lib.homeManagerConfiguration {
          pkgs = Variables.pkgs;
          extraSpecialArgs = { inherit Variables; };
          modules = [
            ./home.nix
            ./modules/home/xdg.nix
            ./modules/home/gtk.nix
          ];
        };
      };
    };
}

.

“Ok then it might be good, I don’t know exactly your case”

It’s just typical newbie case where everything looks like Greek to me. :smiley:

My plan is to have very modular configuration with stuff that I could just swap, like for example kitty.nix module, while heaving tight base configuration.