How can I hide the definition of a NixOS option in one module if it is composed by multiple ones?

1.3k Views Asked by At

The use case is related to Xorg:

By default an xorg.conf is generated by using a template and filling in configuration values. In my setup, the option services.xserver.config which holds the text is defined in <nixos/nixos/modules/services/x11/xserver.nix> (where it is declared) and in <nixos/nixos/modules/services/x11/hardware/synaptics.nix>. The option is of type line, which means that multiple definitions are appended, interspersed by newlines, becoming a single string.

Now I want to override (in fact remove) the part generated by xserver.nix to get auto detection for my graphics hardware while preserving the settings by synaptics.nix. In other words, I want to hide the definition by xserver.nix, preserving all other definitions.

If I override it using services.xserver.config = mkOverride 0 "" then the whole content is deleted because only the definitions with the least priority are applied.

Therefore I tried disabling the xserver module and importing it again in a wrapper module, hiding the single option:

# xserver.nix # wrapper module
args@{ lib, pkgs, pkgs_i686, config,  ... }:

let
  super = import <nixos/nixos/modules/services/x11/xserver.nix> args;
in lib.recursiveUpdate super {
  imports = []; # the imports are not disabled recursively by disabling
                # the including module in the following:
  disabledModules = [ "services/x11/xserver.nix" ];
  config.services.xserver.config = "";
}

This did not change anything.

So I tried the following:

# xserver2.nix # wrapper module 2
args@{ lib, pkgs, pkgs_i686, config,  ... }:

let
  super = import <nixos/nixos/modules/services/x11/xserver.nix> args;
in {
  options = super.options;
  disabledModules = [ "services/x11/xserver.nix" ];
  config = lib.recursiveUpdate super.config {
    services.xserver.config = "";
  };
}

This didn't change anything either. Somehow the old definition still gets exported. NixOS configuration seems mysteriously stateful!?!?

Is there any possibility to achieve what I want without forking the package?

1

There are 1 best solutions below

0
On

I think this is due to merges in the NixOS module system. I put your wrappers into nix-repl and as you say they do not override the config from services/x11/xserver.nix. However in wrapper2 I altered the config that's passed to services/x11/xserver.nix and that does override the xserver.nix config.

# xserver3.nix # wrapper module 3
args@{ lib, pkgs, pkgs_i686, config,  ... }:

let
  basic.config.services.xserver = {
    enable = true;
    synaptics.enable = true;
  };

  super = import <nixpkgs/nixos/modules/services/x11/xserver.nix> args // basic;
in {
  options = super.options;
  disabledModules = [ "services/x11/xserver.nix" ];
  config = lib.recursiveUpdate super.config {
    services.xserver.config = "";
  };
}

Here's the (cut down) output from nix-repl:

nix-repl> evalConfig = import <nixpkgs/nixos/lib/eval-config.nix>

nix-repl> basic = { config.services.xserver = { enable = true; synaptics.enable = true; }; }
nix-repl> result2 = evalConfig { modules = [ basic ./wrapper2.nix ]; }
nix-repl> result2.config.services.xserver.config
"# Automatically enable the synaptics driver... // services/x11/hardware/synaptics.nix
Section "ServerFlags"... EndSection // services/x11/xserver.nix

nix-repl> result3 = evalConfig { modules = [ ./wrapper3.nix ]; }
nix-repl> result3.config.services.xserver.config
"# Automatically enable the synaptics driver... // services/x11/hardware/synaptics.nix only

I think that the config in your initial wrappers are being merged somehow with config that don't have the services/x11/xserver.nix module disabled, and so your changes are just getting overridden again.

Unless anyone else has a more helpful answer for your question here then it might be helpful for you to ask in the NixOS IRC channel, otherwise you could always look through the NixOS module system source to try and work out how best to handle overriding the xserver.nix config (the source is a bit of a headache at first but once you get your head round the recursion it is not too bad).