Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot import a custom nixosModule in a separate file #274

Open
TakodaS opened this issue Feb 27, 2025 · 3 comments
Open

Cannot import a custom nixosModule in a separate file #274

TakodaS opened this issue Feb 27, 2025 · 3 comments

Comments

@TakodaS
Copy link

TakodaS commented Feb 27, 2025

I am unable to import custom modules from a local file and use them in my own nixosConfigurations. For some reason the moduleWithSystem argument is not passed to paths under flake.imports even though the documentation would lead me to believe this is the case.

nix build .#nixosConfigurations.mymodule1.config.system.build.toplevel give me error: attribute 'moduleWithSystem' missing
nix build .#nixosConfigurations.mymodule2.config.system.build.toplevel works, only erroring out later because the configuration is not bootable.

# flake.nix
{
  description = "A Nix-flake-based Nix development environment";

  outputs =
    inputs@{
      self,
      nixpkgs,
      flake-parts,
      ...
    }:
    flake-parts.lib.mkFlake { inherit inputs; } (
      top@{ moduleWithSystem, withSystem, ... }:
      {
        systems = nixpkgs.lib.systems.flakeExposed;
        flake = {
          imports = [
            ./mymodule1.nix
          ];
          nixosModules.mymodule2 = moduleWithSystem (
            perSystem@{ config }: # NOTE: only explicit params will be in perSystem
            nixos@{ pkgs, ... }:
            {
              services.httpd.enable = true;
            }
          );
          nixosConfigurations =
            let
              inherit (nixpkgs.lib.attrsets) mapAttrs;
            in
            mapAttrs (
              _name: value:
              nixpkgs.lib.nixosSystem {
                system = "x86_64-linux";
                modules = [
                  value
                ];
              }
            ) self.nixosModules;

        };
      }
    );
}
# ./mymodule1.nix
{ moduleWithSystem, ... }:
{
  nixosModules.mymodule1 = moduleWithSystem (
    perSystem@{ config }: # NOTE: only explicit params will be in perSystem
    nixos@{ ... }:
    {
      services.httpd.enable = true;
    }
  );
}

EDIT: as a bonus, it would be nice do something like

# flake.nix
nixosModules.mymodule3 = importWithSystem ./mymodule3.nix
@TakodaS TakodaS changed the title Cannot import a custom nixosModule Cannot import a custom nixosModule in a separate file Feb 27, 2025
@roberth
Copy link
Member

roberth commented Feb 27, 2025

I see that you're importing into the flake option, which I've completely failed to anticipate.
None of the module arguments are propagated into that submodule, because I was expecting everyone to treat it as a data container whereas all the "programming" happens in the root.

The following would fix it.

         systems = nixpkgs.lib.systems.flakeExposed;
-        flake = {
-          imports = [
-            ./mymodule1.nix
-          ];
+        imports = [
+          ./mymodule1.nix
+        ];
+        flake = {
 # ./mymodule1.nix
 { moduleWithSystem, ... }:
 {
-  nixosModules.mymodule1 = moduleWithSystem (
+  flake.nixosModules.mymodule1 = moduleWithSystem (
     perSystem@{ config }: # NOTE: only explicit params will be in perSystem

I don't think flake.imports should be used, because everything can be done in the root's imports instead. I'd like to add a warning to it, but that probably requires a module system change.

@TakodaS
Copy link
Author

TakodaS commented Feb 27, 2025

In https://flake.parts/getting-started.html we find

outputs = inputs@{ flake-parts, ... }:
  flake-parts.lib.mkFlake { inherit inputs; } {
    flake = {
      # Put your original flake attributes here.
    };
    systems = [
      # systems for which you want to build the `perSystem` attributes
      "x86_64-linux"
      # ...
    ];
    perSystem = { config, ... }: {
    };
  };

This strongly suggests putting top-level imports under flake, which I think makes more sense. Furthermore, adding the argument top@{ moduleWithSystem, withSystem, ... }: was very difficult to figure out. I think its arguments should be passed to modules under flake by default.

@roberth
Copy link
Member

roberth commented Feb 27, 2025

Thank you for connecting this back to that page. I think this would have helped:

I think its arguments should be passed to modules under flake by default.

Right, I think it's important to make a distinction here.

  • Passing them to the flake submodule. This would enable your original code to work, but it would also give rise to more modules that are expected to be loaded into flakes instead of the root. This creates two classes of modules, and more incompatibilities and confusion that aren't necessary.

  • Passing them to flake.nixosModules, flake.modules.*.*, etc. This is useful, but needs to be managed with care. There's some subtleties involved especially when modules are meant to be consumed by other flakes as well. For instance, your modules may be competing with other flake-parts based modules, and they shouldn't create a requirement for any specialArgs to be defined by the user. I think something could be done, but preferably with new options that generate flake.* definitions. There's no way around flake.*, so those options must be general and simple.

  • Passing them to flake.nixosConfigurations.* etc. This can't be an implicit thing for sure, but the details are something for NixOS configuration modules (e.g. those on flake.parts) to choose and implement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants