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

Anonymous NixOS modules (e.g. from flakes) cannot be disabled #114131

Open
jorsn opened this issue Feb 23, 2021 · 13 comments
Open

Anonymous NixOS modules (e.g. from flakes) cannot be disabled #114131

jorsn opened this issue Feb 23, 2021 · 13 comments
Labels
0.kind: bug Something is broken 6.topic: module system About "NixOS" module system internals

Comments

@jorsn
Copy link
Member

jorsn commented Feb 23, 2021

Describe the bug

An anonymous NixOS module (not included in imports by path but as a function/attr set) cannot be disabled, both because on import the module key is not specific to a module but to an import and because filterModules tries to convert all non-string elements of disabledModules to strings, probably expecting them to be paths.

This defeats the standardized nixosModules api of flakes, since one must rely on the file structure for importing and disabling for disabledModules to work.

To Reproduce

  1. add disabledModules = [ {} ]; to configuration.nix
  2. try to nixos-rebuild build
  3. Result:
[root@longitude-j:/etc/nixos]# nixos-rebuild build
building Nix...
error: --- TypeError ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix-instantiate
at: (200:81) in file: /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix

   199|         let
   200|           moduleKey = m: if isString m then toString modulesPath + "/" + m else toString m;
      |                                                                                 ^
   201|           disabledKeys = map moduleKey disabled;

cannot coerce a set to a string

Expected behavior

If possible, modules should probably get a unique key, regardless of how they are given. This should also be used in disabledModules.

@jorsn jorsn added the 0.kind: bug Something is broken label Feb 23, 2021
@jorsn jorsn changed the title Anonymous modules (e.g. from flakes) cannot be disabled Anonymous NixOS modules (e.g. from flakes) cannot be disabled Feb 23, 2021
@veprbl veprbl added the 6.topic: module system About "NixOS" module system internals label Feb 23, 2021
@SCOTT-HAMILTON
Copy link
Contributor

SCOTT-HAMILTON commented Feb 23, 2021

I know that it's quite straightforward but I still think that it's better to rely on a test machine than to rebuild your own config.

import ./make-test-python.nix ({ pkgs, ... }: {
  name = "test";

  nodes.test = { pkgs, ... }: { disabledModules = [ {} ]; };

  testScript = ''
  '';
})

@bqv
Copy link
Contributor

bqv commented Feb 25, 2021

So surely the answer is don't use anonymous modules?

Edit: oh, for what it's worth, just because the module isn't in nixpkgs, doesn't mean it's de-facto anonymous. None of the ones in my flake are - I had to ensure that to make manual building work

@jorsn
Copy link
Member Author

jorsn commented Feb 25, 2021

@bqv: Every module you access over the flake API (the attr nixosModules) is anonymous, as is every module you access over the NUR. To not use it anonymously, you have to utilize the underlying file structure, which defeats one main purpose of flakes, namely a consistent Nix API for different projects.

What do you mean by “manual building”?

@bqv
Copy link
Contributor

bqv commented Feb 25, 2021

Yes. Caring about file structure is not against the flake api imo, hence why flakes can be coerced to paths like any other derivation.

Manual building = the act of building the manual...

@jorsn
Copy link
Member Author

jorsn commented Feb 25, 2021

It's not against the flake api, but it circumvents it. It doesn't use the flake API, so it defeats the reason for using flakes. You can simply use any fixed-output derivation for fetching or declare a non-flake input to a flake, if you don't want to use a consistent api.

Why are you using Nix in the first place if you can use Linux From Scratch? What do you need Linux for if you can write your own kernel and directly access hardware? Because of abstraction. Imagine a flake whose file tree is littered with modules in 50 different places but exposing the standardized flake API. You have to look at every file to know if it's a module. You don't want to include every single one by path, do you?

@bqv
Copy link
Contributor

bqv commented Feb 25, 2021

You can't be serious...

@Pacman99
Copy link
Contributor

I've been running into this and it is pretty frustrating. disabledModules becomes very hard to use with flakes. Not really sure how this could be solved though, I don't think it's possible to compare anonymous functions.

@jorsn
Copy link
Member Author

jorsn commented Mar 26, 2021

You can still override modules by path, but you must rely on the file system structure of the flakes. The store dir of an input flake foo is "${foo}".

The modules aren't necessarily anonymous functions. They can be attrsets, functions or functors (i.e. attrsets containing an attr __functor = self: f for some function f). Functions and functors are treated equally, but functors could carry metadata like a module key. One could e.g. derive the key from an attribute path of a module, but lib.evalModules would have to be adapted to make use of this information.

@noonien
Copy link

noonien commented Jun 5, 2021

Edit: The issue was my lack of understanding of how nixos modules work, coupled with how declarative nixos containers work. disabledModules are not passed into the declared containers (which should be expected).

I think I bumped into this issue, is there a workaround?

Neither

disabledModules = [ "${modulesPath}/services/web-apps/restya-board.nix" ];
disabledModules = [ "services/web-apps/restya-board.nix" ];

seem to work, and there doesn't seem to be any examples or documentation on how to replace a module in a flaked configuration.

Any ideas?

@mvnetbiz
Copy link
Contributor

mvnetbiz commented Sep 18, 2021

filterModules does not convert all non-string elements. The cause is that since #49401 eval-config.nix passes modulesPath as a string, causing filterModules to always append modulesPath an extra time. You can fix it in your config by turning it back into a path like this. You should be able to add a path referencing a Flake's nixosModules to disabledModules.

{ config, pkgs, lib, modulesPath, ... }:

{
  imports = [
    "${modulesPath}/installer/sd-card/sd-image.nix"
  ];

  disabledModules = map (m: /. + "${modulesPath}/${m}") [
    "profiles/all-hardware.nix"
  ];
}

montchr added a commit to montchr/dotfield that referenced this issue Apr 19, 2022
the upstream module cannot be disabled easily or possibly at all when
using flakes...

NixOS/nixpkgs#114131
@stale
Copy link

stale bot commented Apr 25, 2022

I marked this as stale due to inactivity. → More info

@vikanezrimaya
Copy link
Member

Still important.

(I use all of my custom modules via flake attributes, and if I were to need to disable a module pulled by another module, that would be a major source of pain.)

@Lyndeno
Copy link
Contributor

Lyndeno commented Mar 9, 2024

Still important to me as well. Had to reference a flake module by path to get my config to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
0.kind: bug Something is broken 6.topic: module system About "NixOS" module system internals
Projects
None yet
Development

No branches or pull requests

9 participants