Whats wrong? `/etc/nixos/configuration.nix' has an unsupported attribute `boot'

Happened during a nixos-rebuild, I’m pretty sure I didn’t mess up anything, and I just changed a value in

Module `/etc/nixos/configuration.nix' has an unsupported attribute `boot'. This is caused by introducing a top-level `config' or `options' attribute. Add configuration attributes immediately on the top le
vel instead, or move all of them (namely: boot environment fonts hardware home-manager i18n networking nix nixpkgs programs security services sound system time users virtualisation xdg zramSwap) into the explici
t `config' attribute.
1 Like

Could you show your configuration file? You’ve clearly made some mistake, hard to argue with the tool that interprets your code :wink:

I’ve searched for all occurrences of boot
opened in two editor
and even looked for unicode hidden chars (maybe a zwnj be in the boot causing issue),
this is all of my lines starting with boot

other lines are still needed as well?

  boot.loader.grub = {
    extraConfig = "set theme=($drive2)${pkgs.breeze-grub}/grub/themes/breeze/theme.txt"; # fix
    splashImage = null;
  };
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  boot.loader.efi.efiSysMountPoint = "/boot/efi";
  boot.initrd.secrets = {
    "/crypto_keyfile.bin" = null;
  };
  boot.initrd.luks.devices."luks-x".device = "/dev/disk/by-uuid/x";
  boot.initrd.luks.devices."luks-x".keyFile = "/crypto_keyfile.bin";
  boot.kernelPackages = pkgs.linuxPackages_latest;
  boot.supportedFilesystems = [ "ntfs" ];

isn’t the msg its printing contradicting? what can ever cause it even!

this is my configuration.nix start:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      <home-manager/nixos>
    ];

  nix.settings.experimental-features = [ "nix-command" "flakes" ];
  # nix.readOnlyStore = false;
  nix.extraOptions = ''
    plugin-files = ${pkgs.nix-doc}/lib/libnix_doc_plugin.so
  '';

  boot.loader.grub = {
    extraConfig = "set theme=($drive2)${pkgs.breeze-grub}/grub/themes/breeze/theme.txt"; # fix
    splashImage = null;
  };
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  boot.loader.efi.efiSysMountPoint = "/boot/efi";

  zramSwap = {
    enable = true;
    numDevices = 2;
    swapDevices = 1;
    memoryPercent = 50;
  };

  # Setup keyfile
  boot.initrd.secrets = {
    "/crypto_keyfile.bin" = null;
  };

  # Enable swap on luks
  boot.initrd.luks.devices."luks-x".device = "/dev/disk/by-uuid/x";
  boot.initrd.luks.devices."luks-x".keyFile = "/crypto_keyfile.bin";

  boot.kernelPackages = pkgs.linuxPackages_latest;

  boot.supportedFilesystems = [ "ntfs" ];

So, nixos modules alllow two syntaxes:

{
  imports = [ <some imports> ];
  my-favorite-option = true;
}

and

{
  imports = [ <some imports> ];
  options = { <some custom options> };
  config = {
    my-favorite-option = true;
  };
}

This can be confusing, but the latter syntax is used to define custom options, whereas the former is just used to set them. config in the latter should contain any options the module sets, and usually contains a whole bunch of conditionals so that it changes based on what is set with the options.

The way it works is that if you omit options and config, all keys will simply be treated as if they were in config.

However, if you define a config and try to set options at the same time, nix won’t be able to distinguish between these two modes, and you get the error message you have.

The reason it talks about boot is simply because it’s the first problem it encountered.

Thus, while looking for boot is nice and all, I really need to see your full config file to se where you went wrong. You probably added an options or config somewhere :slight_smile:

9 Likes

Right, I wish the output would have mentioned to look for option and config clearly
the following line, caused me this issue
config.firefox.enablePlasmaBrowserIntegration = true;

Thanks for descriptive respond!

1 Like

To be fair, it literally says:

This is caused by introducing a top-level config' or options’ attribute.

I suppose it could use fewer technical terms to describe that, I imagine new users may be confused by “top-level” and “attribute”.

Far from the worst error message, though.

1 Like

I expected by top level it means, out of the main double curly brackets, but yep its probably due to my noob-ness

Thank you for the explanation. I now understood what is wrong with my configuration (why the error is being triggered) but I am unsure how I should go about fixing it. This is the incriminated file:

{
  inputs,
  lib,
  config,
  osConfig,
  pkgs,
  ...
}:

{

  imports = [
  ];

  options = {
    homeConf.udiskie.enable = lib.mkOption {
      type = lib.types.bool;
      default = false;
      description = "Enable udiskie module";
    };
  };

  osConfig = lib.mkIf config.homeConf.udiskie.enable {
    services.udisks2.enable = true;
  };

  config = lib.mkIf config.homeConf.udiskie.enable {
    services.udiskie.enable = true;
  };

}

Essentially, to have the functionality I want (automount of USB thumb drives) I need to enable two services: one in home-manager and one in nixos proper.

Obviously I could simply create two different files each one with their option and config. It works. However it certainly feels like an anti-pattern to have a functionality split in two independently controlled files (that is: having to keep in sync the value of 2 different options).

What is the proper, idiomatic way to achieve what I want?

I’m curious as well. Have you found out a solution yet?

After a couple of hours of trying to get stuff working with Haumea, I used GitHub - vic/import-tree: Import all nix files in a directory tree.

In 5 minutes I had something working fine.

How did that project solve the described issue? Surely a thing that automatically imports multiple split modules can’t solve the problem that you can’t actually split your module in the first place?


To actually answer the question, though, I don’t think there is an “idiomatic” approach. This comes down to opinion.

The perceived problem is duplication of services between home-manager and NixOS (because there is a user and system service which do “the same” thing).

Personally, I argue that the correct approach is to keep home-manager and NixOS configuration separate, and not view this as a problem in the first place, because fundamentally you should not be mixing system-wide and user-specific configuration.

If you want to pretend there is no difference between user and system services though, and view them as components of the same thing that must therefore be in the same file, you can do that pretty easily in a NixOS module:

{
  services.udisks.enable = true;
  home-manager.sharedModules = [{
    services.udiskie.enable = true;
  }];
}
2 Likes

I’ve spent half of the day trying to use Haumea and remove all the imports = from my project… without luck. I’m pretty sure I was doing something wrong, but I couldn’t find the issue. By chance, I have found the project vic/import-tree and everything worked in 5 minutes.

I have updated my own repo using that library: refactor: use `vic/import-tree` · drupol/nixos-x260@96b9140 · GitHub

I also updated one project at work: refactor: use `vic/import-tree` (94f67ac5) · Commits · ECPHP / Devs profile · GitLab