How to remove an attribute from another NixOS file?

Hi,

Let’s say that I have a nix file containing the following:

{ config, ... }:

{
  networking.hosts = {
    "192.168.1.50" = [ "host1" ];
    "192.168.1.100" = [ "hosttoberemoved" ];
  };
}

Is it possible to import the file and remove networking.hosts.“192.168.1.50”?

I have tried something like:

{ config, ... }:

{
  imports = [ ./hosts.nix ];
  networking.hosts = builtins.removeAttrs config.networking.hosts [ "192.168.1.100" ];
}

but I am getting obviously infinite recursion encountered.

The recursion comes from using config.networking.hosts to compute config.networking.hosts in:

networking.hosts = builtins.removeAttrs config.networking.hosts [ "192.168.1.100" ];

(import ./hosts.nix { config = null; }).networking.hosts will give you the host attr set. Rather then a module you probably want a different format. For example:

{
    "192.168.1.50" = [ "host1" ];
    "192.168.1.100" = [ "hosttoberemoved" ];
}

Then you can just use:

{ config, ... }:

{
  networking.hosts = builtins.removeAttrs (import ./hosts.nix) [ "192.168.1.100" ];
}
1 Like

What if I do not have the luxury of modifying the underlying files and the import took place already elsewhere, is there a way to remove it?

A workaround I thought of, was resetting the host I want to remove, e.g.:

{ config, lib, ... }:

{
  networking.hosts."192.168.1.100" = lib.mkForce [];
}

but this does not effectively remove the attribute.

Hi,

NixOS module system forces you to not do this. Some time ago I was puzzled with a similar question https://stackoverflow.com/questions/39090461/exclude-predefined-package-in-environment-systempackages

The “NixOS Way” is to modify your first module like this:


{ config, lib, ... }: {
  options.absentHosts = lib.mkOption {

    default = [];

  };

  config = { networking.hosts = lib.flip builtins.removeAttrs config.absentHosts { "192.168.1.50" = [ "host1" ]; "192.168.1.100" = [ "hosttoberemoved" ]; };

  };

}

And declare the newly created option in your second module:


{ config, ... }: { imports = [ ./hosts.nix ]; absentHosts = [ "192.168.1.100" ]; }
{ config, lib, ... }:

{
  imports = [ ./hosts.nix ];
  networking.hosts = lib.mkForce (let hostsModule = import <nixpkgs/nixos> {
       configuration = {
          imports = [ ./hosts.nix ];
       };  };
       in builtins.removeAttrs hostsModule.config.networking.hosts [ "192.168.1.100" ]
  );
}

Checking

$ nixos-option -I nixos-config=$PWD/configuration.nix networking.hosts
Value:
{ "192.168.1.50" = [ "host1" ]; }
1 Like

I think you could also use extendModules to achieve the same goal (which in my opinion is a big limitation that requires an ugly workaround). As soon as I’ve time I’ll try to see it works.