diff --git a/docs/Getting Started/NixOS/Root on ZFS/1-preparation.rst b/docs/Getting Started/NixOS/Root on ZFS/1-preparation.rst index 0370768..311d860 100644 --- a/docs/Getting Started/NixOS/Root on ZFS/1-preparation.rst +++ b/docs/Getting Started/NixOS/Root on ZFS/1-preparation.rst @@ -8,7 +8,7 @@ Preparation #. Disable Secure Boot. ZFS modules can not be loaded if Secure Boot is enabled. #. Download `NixOS Live Image - `__ and boot from it. + `__ and boot from it. #. Connect to the Internet. #. Set root password or ``/root/.ssh/authorized_keys``. #. Start SSH server:: @@ -17,15 +17,15 @@ Preparation #. Connect from another computer:: - ssh root@192.168.1.19 + ssh root@192.168.1.91 #. Target disk List available disks with:: - ls /dev/disk/by-id/* + find /dev/disk/by-id/ - If using virtio as disk bus, use ``/dev/disk/by-path/*``. + If using virtio as disk bus, use ``/dev/disk/by-path/``. Declare disk array:: @@ -37,11 +37,10 @@ Preparation #. Set partition size: - Set swap size. It's `recommended `__ - to setup a swap partition. If you intend to use hibernation, - the minimum should be no less than RAM size. Skip if swap is not needed:: + Set swap size, set to 1 if you don't want swap to + take up too much space:: - INST_PARTSIZE_SWAP=8 + INST_PARTSIZE_SWAP=4 Root pool size, use all remaining disk space if not set:: diff --git a/docs/Getting Started/NixOS/Root on ZFS/2-system-installation.rst b/docs/Getting Started/NixOS/Root on ZFS/2-system-installation.rst index 0c3ad69..4d6f3eb 100644 --- a/docs/Getting Started/NixOS/Root on ZFS/2-system-installation.rst +++ b/docs/Getting Started/NixOS/Root on ZFS/2-system-installation.rst @@ -16,7 +16,7 @@ System Installation sgdisk -n2:0:+4G -t2:BE00 $i - test -z $INST_PARTSIZE_SWAP || sgdisk -n4:0:+${INST_PARTSIZE_SWAP}G -t4:8200 $i + sgdisk -n4:0:+${INST_PARTSIZE_SWAP}G -t4:8200 $i if test -z $INST_PARTSIZE_RPOOL; then sgdisk -n3:0:0 -t3:BF00 $i @@ -25,6 +25,12 @@ System Installation fi sgdisk -a1 -n5:24K:+1000K -t5:EF02 $i + + sync && udevadm settle && sleep 3 + + cryptsetup open --type plain --key-file /dev/random $i-part4 ${i##*/}-part4 + mkswap /dev/mapper/${i##*/}-part4 + swapon /dev/mapper/${i##*/}-part4 done #. Create boot pool:: @@ -84,9 +90,7 @@ System Installation If not using a multi-disk setup, remove ``mirror``. -#. This section implements dataset layout as described in `overview <1-preparation.html>`__. - - Create root system container: +#. Create root system container: - Unencrypted:: @@ -108,18 +112,25 @@ System Installation -o keyformat=passphrase \ rpool/nixos - Create system datasets:: + You can automate this step (insecure) with: ``echo POOLPASS | zfs create ...``. - zfs create -o canmount=on -o mountpoint=/ rpool/nixos/root - zfs create -o canmount=on -o mountpoint=/home rpool/nixos/home - zfs create -o canmount=off -o mountpoint=/var rpool/nixos/var - zfs create -o canmount=on rpool/nixos/var/lib - zfs create -o canmount=on rpool/nixos/var/log + Create system datasets, let NixOS declaratively + manage mountpoints with ``mountpoint=legacy``:: - Create boot dataset:: - - zfs create -o canmount=off -o mountpoint=none bpool/nixos - zfs create -o canmount=on -o mountpoint=/boot bpool/nixos/root + zfs create -o mountpoint=legacy rpool/nixos/root + mount -t zfs rpool/nixos/root /mnt/ + zfs create -o mountpoint=legacy rpool/nixos/home + mkdir /mnt/home + mount -t zfs rpool/nixos/home /mnt/home + zfs create -o mountpoint=legacy rpool/nixos/var + zfs create -o mountpoint=legacy rpool/nixos/var/lib + zfs create -o mountpoint=legacy rpool/nixos/var/log + zfs create -o mountpoint=none bpool/nixos + zfs create -o mountpoint=legacy bpool/nixos/root + mkdir /mnt/boot + mount -t zfs bpool/nixos/root /mnt/boot + zfs create -o mountpoint=legacy rpool/nixos/empty + zfs snapshot rpool/nixos/empty@start #. Format and mount ESP:: diff --git a/docs/Getting Started/NixOS/Root on ZFS/3-system-configuration.rst b/docs/Getting Started/NixOS/Root on ZFS/3-system-configuration.rst index e969d0a..7bbb28f 100644 --- a/docs/Getting Started/NixOS/Root on ZFS/3-system-configuration.rst +++ b/docs/Getting Started/NixOS/Root on ZFS/3-system-configuration.rst @@ -6,83 +6,48 @@ System Configuration .. contents:: Table of Contents :local: -#. Generate initial system configuration:: +#. Download system configuration from this repo:: - nixos-generate-config --root /mnt + mkdir -p /mnt/etc/nixos/ + curl -o /mnt/etc/nixos/configuration.nix -L \ + https://github.com/openzfs/openzfs-docs/raw/master/docs/Getting%20Started/NixOS/Root%20on%20ZFS/configuration.nix -#. Import ZFS-specific configuration:: +#. Customize configuration to your hardware:: - sed -i "s|./hardware-configuration.nix|./hardware-configuration.nix ./zfs.nix|g" /mnt/etc/nixos/configuration.nix + for i in $DISK; do + sed -i \ + "s|PLACEHOLDER_FOR_DEV_NODE_PATH|\"${i%/*}/\"|" \ + /mnt/etc/nixos/configuration.nix + break + done -#. Configure hostid:: - - tee -a /mnt/etc/nixos/zfs.nix <>/mnt/etc/nixos/zfs.nix - done - - tee -a /mnt/etc/nixos/zfs.nix <`__. + Apply your own hardware configuration in this file, + then execute:: + + nixos-rebuild boot + + Then reboot. You may need to make certain + adjustments to where configuration files are stored, + see `NixOS wiki `__ for + details. + +Replace a failed disk +===================== + +When a disk fails in a mirrored setup, the disk can be +replaced with the following procedure. + +#. Shutdown the computer. + +#. Replace the failed disk with another disk. The + replacement should be at least the same size or + larger than the failed disk. + +#. Boot the computer. When a disk fails, the system will boot, albeit + several minutes slower than normal. This is due to + the initrd and systemd designed to only import a pool + in degraded state after a 90s timeout. Swap + partition on that disk will also fail. + +#. Launch a ephemeral nix shell with gptfdisk:: + + nix-shell -p gptfdisk + +#. Identify the bad disk and a working old disk:: + + ZPOOL_VDEV_NAME_PATH=1 zpool status + + pool: bpool + status: DEGRADED + action: Replace the device using 'zpool replace'. + ... + config: bpool + mirror-0 + 2387489723748 UNAVAIL 0 0 0 was /dev/disk/by-id/ata-BAD-part2 + /dev/disk/by-id/ata-OLD-part2 ONLINE 0 0 0 + +#. Store the bad disk and a working old disk in a variable, omit the partition number ``-partN``:: + + BAD=/dev/disk/by-id/ata-BAD + OLD=/dev/disk/by-id/ata-OLD + +#. Identify the new disk:: + + find /dev/disk/by-id/ + + /dev/disk/by-id/ata-OLD-part1 + /dev/disk/by-id/ata-OLD-part2 + ... + /dev/disk/by-id/ata-OLD-part5 + /dev/disk/by-id/ata-NEW <-- new disk w/o partition table + +#. Store the new disk in a variable:: + + NEW=/dev/disk/by-id/ata-NEW + +#. Replicate partition table on the new disk:: + + sgdisk -Z $NEW + sgdisk --backup=backup $OLD + sgdisk --load-backup=backup $NEW + sgdisk --randomize-guids $NEW + +#. If the new disk is larger than the old disk, expand root pool partition size:: + + sgdisk --delete=3 $NEW + + # expand to all remaining disk space + sgdisk -n3:0:0 -t3:BF00 $NEW + + Note that this space will only become available once all disks in the mirrored pool are + replaced with larger disks. + +#. Format and mount EFI system partition:: + + mkfs.vfat -n EFI ${NEW}-part1 + mkdir -p /boot/efis/${NEW##*/}-part1 + mount -t vfat ${NEW}-part1 /boot/efis/${NEW##*/}-part1 + +#. Replace failed disk in pool:: + + zpool offline bpool ${BAD}-part2 + zpool offline rpool ${BAD}-part3 + zpool replace bpool ${BAD}-part2 ${NEW}-part2 + zpool replace rpool ${BAD}-part3 ${NEW}-part3 + zpool online bpool ${NEW}-part2 + zpool online rpool ${NEW}-part3 + + Let the new disk resilver. Check status with ``zpool status``. + +#. Update NixOS system configuration:: + + sed -i "s|${BAD##*/}|${NEW##*/}|" /etc/nixos/machine.nix + +#. Apply the updated NixOS system configuration, reinstall bootloader, then reboot:: + + nixos-rebuild boot --install-bootloader + + reboot diff --git a/docs/Getting Started/NixOS/Root on ZFS/configuration-immutable.nix b/docs/Getting Started/NixOS/Root on ZFS/configuration-immutable.nix new file mode 100644 index 0000000..e696d0d --- /dev/null +++ b/docs/Getting Started/NixOS/Root on ZFS/configuration-immutable.nix @@ -0,0 +1,252 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). +{ config, lib, pkgs, modulesPath, ... }: + +let + zfsRoot.partitionScheme = { + biosBoot = "-part5"; + efiBoot = "-part1"; + swap = "-part4"; + bootPool = "-part2"; + rootPool = "-part3"; + }; + zfsRoot.devNodes = PLACEHOLDER_FOR_DEV_NODE_PATH; # MUST have trailing slash! /dev/disk/by-id/ + zfsRoot.bootDevices = (import ./machine.nix).bootDevices; + zfsRoot.mirroredEfi = "/boot/efis/"; + +in { + # adjust according to your platform, such as + imports = [ + # (modulesPath + "/profiles/qemu-guest.nix") + # (modulesPath + "/profiles/all-hardware.nix") + (modulesPath + "/installer/scan/not-detected.nix") + ]; + systemd.services.zfs-mount.enable = false; + + # networking.hostName = "nixos"; # Define your hostname. + # Pick only one of the below networking options. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + # networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. + + # Set your time zone. + # time.timeZone = "Europe/Amsterdam"; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Select internationalisation properties. + # i18n.defaultLocale = "en_US.UTF-8"; + # console = { + # font = "Lat2-Terminus16"; + # keyMap = "us"; + # useXkbConfig = true; # use xkbOptions in tty. + # }; + + # Enable the X11 windowing system. + + # Configure keymap in X11 + # "eurosign:e"; + # "caps:escape" # map caps to escape. + # }; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; + + # Enable touchpad support (enabled default in most desktopManager). + + # Define a user account. Don't forget to set a password with ‘passwd’. + # users.users.alice = { + # isNormalUser = true; + # extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + # packages = with pkgs; [ + # firefox + # thunderbird + # ]; + # }; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; + [ + # vim + ## Do not forget to add an editor to edit configuration.nix! + ## The Nano editor is also installed by default. + # wget + mg + ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = false; + users.users.root = { + ##hash: mkpasswd -m SHA-512 -s + initialHashedPassword = PLACEHOLDER_FOR_ROOT_PWD_HASH; + openssh.authorizedKeys.keys = [ + ]; + }; + programs.git.enable = true; + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + system.copySystemConfiguration = true; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + boot.initrd.availableKernelModules = [ + "ahci" + "xhci_pci" + "virtio_pci" + "virtio_blk" + "ehci_pci" + "nvme" + "uas" + "sd_mod" + "sr_mod" + "sdhci_pci" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems = { + "/" = { + device = "rpool/nixos/empty"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + + "/oldroot" = { + device = "rpool/nixos/root"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + neededForBoot = true; + }; + + "/nix" = { + device = "/oldroot/nix"; + fsType = "none"; + options = [ "bind" "X-mount.mkdir" ]; + }; + + "/etc/nixos" = { + device = "/oldroot/etc/nixos"; + fsType = "none"; + options = [ "bind" "X-mount.mkdir" ]; + }; + + "/home" = { + device = "rpool/nixos/home"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + + "/var/lib" = { + device = "rpool/nixos/var/lib"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + + "/var/log" = { + device = "rpool/nixos/var/log"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + + "/boot" = { + device = "bpool/nixos/root"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + } // (builtins.listToAttrs (map (diskName: { + name = zfsRoot.mirroredEfi + diskName + zfsRoot.partitionScheme.efiBoot; + value = { + device = zfsRoot.devNodes + diskName + zfsRoot.partitionScheme.efiBoot; + fsType = "vfat"; + options = [ + "x-systemd.idle-timeout=1min" + "x-systemd.automount" + "noauto" + "nofail" + ]; + }; + }) zfsRoot.bootDevices)); + + swapDevices = (map (diskName: { + device = zfsRoot.devNodes + diskName + zfsRoot.partitionScheme.swap; + discardPolicy = "both"; + randomEncryption = { + enable = true; + allowDiscards = true; + }; + }) zfsRoot.bootDevices); + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.networkmanager.enable = true; + # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = + lib.mkDefault config.hardware.enableRedistributableFirmware; + hardware.cpu.amd.updateMicrocode = + lib.mkDefault config.hardware.enableRedistributableFirmware; + + + boot.supportedFilesystems = [ "zfs" ]; + networking.hostId = "abcd1234"; + boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages; + boot.loader.efi.efiSysMountPoint = with builtins; + (zfsRoot.mirroredEfi + (head zfsRoot.bootDevices) + zfsRoot.partitionScheme.efiBoot); + boot.zfs.devNodes = zfsRoot.devNodes; + boot.loader.efi.canTouchEfiVariables = false; + boot.loader.generationsDir.copyKernels = true; + boot.loader.grub.efiInstallAsRemovable = true; + boot.loader.grub.enable = true; + boot.loader.grub.version = 2; + boot.loader.grub.copyKernels = true; + boot.loader.grub.efiSupport = true; + boot.loader.grub.zfsSupport = true; + boot.loader.grub.extraInstallCommands = with builtins; + (toString (map (diskName: + "cp -r " + config.boot.loader.efi.efiSysMountPoint + "/EFI" + " " + + zfsRoot.mirroredEfi + diskName + zfsRoot.partitionScheme.efiBoot + "\n") + (tail zfsRoot.bootDevices))); + boot.loader.grub.devices = + (map (diskName: zfsRoot.devNodes + diskName) zfsRoot.bootDevices); + boot.initrd.postDeviceCommands = '' + zpool import -Nf rpool + zfs rollback -r rpool/nixos/empty@start + zpool export -a + ''; +} + diff --git a/docs/Getting Started/NixOS/Root on ZFS/configuration.nix b/docs/Getting Started/NixOS/Root on ZFS/configuration.nix new file mode 100644 index 0000000..18a9d4b --- /dev/null +++ b/docs/Getting Started/NixOS/Root on ZFS/configuration.nix @@ -0,0 +1,227 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). +{ config, lib, pkgs, modulesPath, ... }: + +let + zfsRoot.partitionScheme = { + biosBoot = "-part5"; + efiBoot = "-part1"; + swap = "-part4"; + bootPool = "-part2"; + rootPool = "-part3"; + }; + zfsRoot.devNodes = PLACEHOLDER_FOR_DEV_NODE_PATH; # MUST have trailing slash! /dev/disk/by-id/ + zfsRoot.bootDevices = (import ./machine.nix).bootDevices; + zfsRoot.mirroredEfi = "/boot/efis/"; + +in { + # adjust according to your platform, such as + imports = [ + # (modulesPath + "/profiles/qemu-guest.nix") + # (modulesPath + "/profiles/all-hardware.nix") + (modulesPath + "/installer/scan/not-detected.nix") + ]; + systemd.services.zfs-mount.enable = false; + + # networking.hostName = "nixos"; # Define your hostname. + # Pick only one of the below networking options. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + # networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. + + # Set your time zone. + # time.timeZone = "Europe/Amsterdam"; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Select internationalisation properties. + # i18n.defaultLocale = "en_US.UTF-8"; + # console = { + # font = "Lat2-Terminus16"; + # keyMap = "us"; + # useXkbConfig = true; # use xkbOptions in tty. + # }; + + # Enable the X11 windowing system. + + # Configure keymap in X11 + # "eurosign:e"; + # "caps:escape" # map caps to escape. + # }; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; + + # Enable touchpad support (enabled default in most desktopManager). + + # Define a user account. Don't forget to set a password with ‘passwd’. + # users.users.alice = { + # isNormalUser = true; + # extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + # packages = with pkgs; [ + # firefox + # thunderbird + # ]; + # }; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; + [ + # vim + ## Do not forget to add an editor to edit configuration.nix! + ## The Nano editor is also installed by default. + # wget + mg + ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = false; + users.users.root = { + ##hash: mkpasswd -m SHA-512 -s + initialHashedPassword = PLACEHOLDER_FOR_ROOT_PWD_HASH; + openssh.authorizedKeys.keys = [ + ]; + }; + programs.git.enable = true; + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + system.copySystemConfiguration = true; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + boot.initrd.availableKernelModules = [ + "ahci" + "xhci_pci" + "virtio_pci" + "virtio_blk" + "ehci_pci" + "nvme" + "uas" + "sd_mod" + "sr_mod" + "sdhci_pci" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems = { + "/" = { + device = "rpool/nixos/root"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + + "/home" = { + device = "rpool/nixos/home"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + + "/var/lib" = { + device = "rpool/nixos/var/lib"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + + "/var/log" = { + device = "rpool/nixos/var/log"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + + "/boot" = { + device = "bpool/nixos/root"; + fsType = "zfs"; + options = [ "X-mount.mkdir" ]; + }; + } // (builtins.listToAttrs (map (diskName: { + name = zfsRoot.mirroredEfi + diskName + zfsRoot.partitionScheme.efiBoot; + value = { + device = zfsRoot.devNodes + diskName + zfsRoot.partitionScheme.efiBoot; + fsType = "vfat"; + options = [ + "x-systemd.idle-timeout=1min" + "x-systemd.automount" + "noauto" + "nofail" + ]; + }; + }) zfsRoot.bootDevices)); + + swapDevices = (map (diskName: { + device = zfsRoot.devNodes + diskName + zfsRoot.partitionScheme.swap; + discardPolicy = "both"; + randomEncryption = { + enable = true; + allowDiscards = true; + }; + }) zfsRoot.bootDevices); + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.networkmanager.enable = true; + # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = + lib.mkDefault config.hardware.enableRedistributableFirmware; + hardware.cpu.amd.updateMicrocode = + lib.mkDefault config.hardware.enableRedistributableFirmware; + + boot.supportedFilesystems = [ "zfs" ]; + networking.hostId = "abcd1234"; + boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages; + boot.loader.efi.efiSysMountPoint = with builtins; + (zfsRoot.mirroredEfi + (head zfsRoot.bootDevices) + zfsRoot.partitionScheme.efiBoot); + boot.zfs.devNodes = zfsRoot.devNodes; + boot.loader.efi.canTouchEfiVariables = false; + boot.loader.generationsDir.copyKernels = true; + boot.loader.grub.efiInstallAsRemovable = true; + boot.loader.grub.enable = true; + boot.loader.grub.version = 2; + boot.loader.grub.copyKernels = true; + boot.loader.grub.efiSupport = true; + boot.loader.grub.zfsSupport = true; + boot.loader.grub.extraInstallCommands = with builtins; + (toString (map (diskName: + "cp -r " + config.boot.loader.efi.efiSysMountPoint + "/EFI" + " " + + zfsRoot.mirroredEfi + diskName + zfsRoot.partitionScheme.efiBoot + "\n") + (tail zfsRoot.bootDevices))); + boot.loader.grub.devices = + (map (diskName: zfsRoot.devNodes + diskName) zfsRoot.bootDevices); +} +