Swap Device does not appear

I have two NixOS configurations:

  • /etc/nixos_works: works fine
  • /etc/nixos_bug: swap device does not appear
    (message at beginning of boot process)

But, in my opinion, the only difference is the order of attributes.
I do not understand, why the order is important.

nixos_works

The luks.device for the swap device is set in machineParameters.nix:

{ pkgs }:
let
  prop = import ./properties.nix { };
  ...
in {
  ...
  attributes = {
    boot.initrd.luks.devices."luks-eb078b50-9cc3-4a8c-b0fc-0008f7c4c1f3".device =
      "/dev/disk/by-uuid/eb078b50-9cc3-4a8c-b0fc-0008f7c4c1f3";
    boot.kernelParams = prop.bootKernelParams;
    ...
  }; # end of attributes
}

which then is imported into configuration.nix:

{ config, pkgs, ... }:
let
  prop = import ./properties.nix { };
  machine = import ./machineParameters.nix { inherit pkgs; };
in {
  imports = [
    ...
  ];
  ...
  system.stateVersion = prop.nixRelease; # Did you read the comment?
} // prop.fileSys // machine.attributes # include machine specific settings

The swap devices appears and I have 16 GiB of swap :slight_smile:

nixos_bug

The luks.device for the swap device is defined directly in configuration.nix and not in machineParameters.nix:

{ config, pkgs, ... }:
let
  prop = import ./properties.nix { };
  machine = import ./machineParameters.nix { inherit pkgs; };
in {
  imports = [
    ...
  ];
  ...
  system.stateVersion = prop.nixRelease; # Did you read the comment?
  boot.initrd.luks.devices."luks-eb078b50-9cc3-4a8c-b0fc-0008f7c4c1f3".device =
    "/dev/disk/by-uuid/eb078b50-9cc3-4a8c-b0fc-0008f7c4c1f3";
} // prop.fileSys // machine.attributes # include machine specific settings

but it does not appear and my swap size is 0B:

free -h
              gesamt       benutzt     frei      gemns.  Puffer/Cache verfügbar
Speicher:       15Gi       759Mi        12Gi       952Mi       1.8Gi        13Gi
Swap:             0B          0B          0B

Difference between nixos_works and nixos_bug

There is really no other difference:

➜  ~ diff -r /etc/nixos_works /etc/nixos_bug

diff --color -r /etc/nixos_works/configuration.nix /etc/nixos_bug/configuration.nix
80a81,83
>   boot.initrd.luks.devices."luks-eb078b50-9cc3-4a8c-b0fc-0008f7c4c1f3".device =
>     "/dev/disk/by-uuid/eb078b50-9cc3-4a8c-b0fc-0008f7c4c1f3";
>

diff --color -r /etc/nixos_works/machineParameters.nix /etc/nixos_bug/machineParameters.nix
44,46d43
<     boot.initrd.luks.devices."luks-eb078b50-9cc3-4a8c-b0fc-0008f7c4c1f3".device =
<       "/dev/disk/by-uuid/eb078b50-9cc3-4a8c-b0fc-0008f7c4c1f3";
<

Does anybody understand why the second configuration fails?

Thanks for your help.

1 Like

gnome-disks

According to gnome-disks the luks device is locked:
luksDeviceSwap

If this issue is solved, it’s best to mark the solution.

But the issue is not solved.

1 Like

My bad, sorry about that.

But, in my opinion, the only difference is the order of attributes.
I do not understand, why the order is important.

The order matters because you are using the update-operator (“//”). From Operators - Nix Reference Manual :

The returned attribute set will have of all the attributes in attrset1 and attrset2. If an attribute name is present in both, the attribute value from the latter is taken.

I suspect that in nixos_bug one of prop.fileSys and machine.attributes is overwriting the attribute set boot. Generally, I prefer to use lib.mkMerge instead of the update-operator, as the former has the behaviour that is usually wanted. E.g., like so:

lib.mkMerge [
  { 
    # some attributes
  }
  prop.fileSys
  machine.attributes
]

That is correct, // does not do a recursive merge. lib.recursiveUpdate would would work.

And in the context of NixOS modules, lib.mkMerge you point out is even better, since Nix-level attribute merging will break some NixOS module system features (e.g. lib.mkIf or lib.mkMerge – those actually return an attribute set, whose attributes Nix would gladly overwrite):

nix-repl> :p lib.mkIf false { foo = [1]; }                                                      
{ _type = "if"; condition = false; content = { foo = [ 1 ]; }; }

nix-repl> :p lib.recursiveUpdate (lib.mkIf false { foo = [1]; }) (lib.mkIf true { foo = [2]; })
{ _type = "if"; condition = true; content = { foo = [ 2 ]; }; }

nix-repl> :p lib.mkMerge [ (lib.mkIf false { foo = [1]; }) (lib.mkIf true { foo = [2]; }) ]     
{ _type = "merge"; contents = [ { _type = "if"; condition = false; content = { foo = [ 1 ]; }; } { _type = "if"; condition = true; content = { foo = [ 2 ]; }; } ]; }

But the simplest solution here is actually an implicit merge using the module system’s imports feature:

{ config, pkgs, ... }:
let
  prop = import ./properties.nix { };
  machine = import ./machineParameters.nix { inherit pkgs; };
in {
  imports = [
    ...
    # include machine specific settings
    prop.fileSys
    machine.attributes
  ];
  ...
}
2 Likes

Thanks for your replies! The keyword was overwriting.
I reorganised and simplified my configuration;
to those who are interested:

1 Like