`mkfs.ext4: is not found` in postResumeCommands

I’m trying to create a nix impermanence setup and I want to wipe the root filesystem on startup. Currently I am trying to reformat the disk using mkfs.ext4 but it seems like the mkfs commands are not present in the initial ram disk.

boot.initrd.postResumeCommands = lib.mkAfter ''
    # Reformat the root disk
    mkfs.ext4 -F -L NIXOS_ROOT /dev/disk/by-label/NIXOS_ROOT
'';

Here are the things I tried:

# Adding ext4 as a kernel module
boot.initrd.kernelModules = [ "ext4" ];

# Adding ext4 as a supported filesystem
boot.initrd.supportedFilesystems = [ "ext4" ];

# Adding e2fsprogs as an extra binary
boot.initrd.systemd.extraBin = {
  "mkfs.ext4" = "${pkgs.e2fsprogs}/bin/mkfs.ext4"
};

# Adding e2fsprogs as an initrd binary
boot.initrd.systemd.initrdBin = [ pkgs.e2fsprogs ];

But I still get the same error: /init: line 831: mkfs.ext4: not found
I’m very new to nix and honestly I have no idea what I’m doing. How do I wipe the root filesystem?

There are two implementations of initrd in NixOS, and initrdBin / extraBin are for the systemd implementation while postResumeCommands is for the scripted (default) implementation. You can either switch to systemd initrd (recommended) with boot.initrd.systemd.enable = true;, or you can add mkfs.ext4 to scripted initrd by using boot.initrd.extraUtilsCommands.

boot.initrd.extraUtilsCommands = ''
  copy_bin_and_libs ${pkgs.e2fsprogs}/bin/mkfs.ext4
'';

Switching to systemd initrd is more complicated, but the scripted initrd will eventually be deprecated and removed. Instead of postResumeCommands, you create a custom systemd service with the necessary dependencies in initrd.

boot.initrd.systemd = {
  enable = true;
  extraBin."mkfs.ext4" = "${pkgs.e2fsprogs}/bin/mkfs.ext4";
  services.wipe-file-systems = {
    unitConfig.DefaultDependencies = false;
    requiredBy = [ "initrd.target" ];
    before = [ "local-fs-pre.target" ];
    after = [ "initrd-root-device.target" "systemd-hibernate-resume.service" ];
    serviceConfig.Type = "oneshot";
    script = ''
      # what you would normally put in 'postResumeCommands'
      ...
    '';
  };
};
2 Likes

Ohhh that makes a lot of sense. Thank you, this is exactly what I needed!