Nix complains during building that I should change my working method to systemd. But I can’t get it to work.
I’m using disko
error:
Failed assertions:
- systemd stage 1 does not support 'boot.initrd.postDeviceCommands'. Please
convert it to analogous systemd units in 'boot.initrd.systemd'.
This worked before but gives the error above:
boot.initrd.postDeviceCommands = lib.mkAfter ''
zfs rollback -r rpool/nixos/local/root@blank
'';
This doesn’t rollback the system after boot:
boot.initrd.systemd.enable = lib.mkDefault true;
boot.initrd.systemd.services.rollback = {
description = "Rollback ZFS datasets to a pristine state";
wantedBy = [
"initrd.target"
];
after = [
"zfs-import-zroot.service"
];
before = [
"sysroot.mount"
];
path = with pkgs; [
zfs
];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = ''
zfs rollback -r rpool/nixos/local/root@blank && echo "rollback complete"
'';
};
other parts of the config:
boot.loader.systemd-boot.enable = false;
boot.loader.grub.enable = true;
boot.loader.grub.efiSupport = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;
boot.initrd.supportedFilesystems = [ "zfs" ]; # boot from zfs
boot.kernelParams = [
"elevator=none" # Because ZFS doesn't have the whole disk, just a partition. Set the disk’s scheduler to none. ZFS takes this step automatically if it does control the entire disk.
"nohibernate" # ZFS misses support for freeze/thaw operations.This means that using ZFS together with hibernation (suspend to disk) may cause filesystem corruption.See https://github.com/openzfs/zfs/issues/260.
# "boot.debug1devices"
];
boot.supportedFilesystems = [ "zfs" ];
boot.zfs.enableUnstable = false;
# boot.zfs.forceImportRoot = false;
# boot.zfs.forceImportAll = false;
# boot.zfs.devNodes = "/dev/disk/by-partlabel/System";
services.udev.extraRules = ''
ACTION=="add|change", KERNEL=="sd[a-z]*[0-9]*|mmcblk[0-9]*p[0-9]*|nvme[0-9]*n[0-9]*p[0-9]*", ENV{ID_FS_TYPE}=="zfs_member", ATTR{../queue/scheduler}="none"
''; # zfs already has its own scheduler. without this (@Artturin)'s computer froze for a second when he nix builds something.
services.zfs = {
autoScrub.enable = true;
trim.enable = true;
autoSnapshot = {
enable = lib.mkDefault true;
frequent = 8; # 15min
hourly = 24; # 60min
daily = 3; # 1d
weekly = 4; # 1w
monthly = 6; # 1m
flags = "-k -p --utc";
};
};
# TODO: Disko doesn't (yet) support marking filesystems as needed for boot.
fileSystems = {
"/".neededForBoot = true;
# "/nix".neededForBoot = true;
# "/cache".neededForBoot = true;
# "/home".neededForBoot = true;
"/persist".neededForBoot = true;
};
disko:
{ disks
, swapInGB
, luks
, zfs_ashift
, zfs_refreservationInGB
, lib
, ...
}:
let
single = (lib.length disks == 1);
in
{
disko.devices = {
disk = lib.genAttrs disks
(device:
let
# NOTE: disk name should not be too long: https://github.com/nix-community/disko/issues/389
# /dev/disk/by-id/ata-xxxxxx131403908
n1 = lib.removePrefix "_" (builtins.replaceStrings [ "/" ] [ "_" ] (builtins.baseNameOf device));
n2 = (lib.concatStrings [ "abcdefg" n1 ]); # Make it long enough if someone would use /dev/sda instead of by-id
stringLength = builtins.stringLength n2;
idLength = 6;
idex1 = builtins.sub stringLength idLength;
n3 = builtins.substring idex1 stringLength n2; # 403908
n4 = (lib.concatStrings [ "main" n3 ]); # main403908
dindex = lib.lists.findFirstIndex (d: d == device) null disks;
in
{
inherit device;
type = "disk";
name = n4;
content = {
type = "gpt";
partitions =
{
boot = {
size = "1M";
type = "EF02"; # for grub MBR
};
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
} // lib.optionalAttrs single {
mountpoint = "/boot";
} // lib.optionalAttrs (!single) {
mountpoint = "/boot${toString dindex}";
mountOptions = [ "nofail" ];
};
};
} // lib.optionalAttrs (swapInGB > 0) {
SWAP = {
size = (lib.concatStrings [ (builtins.toString swapInGB) "G" ]);
content = {
type = "swap";
randomEncryption = true;
resumeDevice = true; # Resume from hiberation from this device
};
};
} // lib.optionalAttrs (!luks) {
ZFS = {
size = "100%";
content = {
type = "zfs";
pool = "rpool";
};
};
} // lib.optionalAttrs luks {
luks = {
size = "100%";
content = {
type = "luks";
name = "crypted";
# passwordFile strips the newline at the end
# keyFile is if the file is there for booting
# additionalKeyFiles are additional key files that can be also used for booting. But they don't need to be present
# # disable settings.keyFile if you want to use interactive password entry
# #passwordFile = "/tmp/secret.key"; # Interactive
# settings = {
# allowDiscards = true;
# keyFile = "/tmp/secret.key";
# };
# additionalKeyFiles = [ "/tmp/additionalSecret.key" ];
content = {
type = "zfs";
pool = "rpool";
};
};
};
};
};
});
zpool.rpool = {
type = "zpool";
mode = lib.mkIf (!single) "mirror";
options = {
ashift = (builtins.toString zfs_ashift);
# Auto trimming could maybe be bad for my SSDs. Will instead have the OS do `zpool trim` on a schedule.
# autotrim = "on";
listsnapshots = "on";
};
rootFsOptions = {
# This is more or less required for certain things to not break, for systemd-journald posixacls are required
acltype = "posixacl";
canmount = "off";
# zstd is slower but compresses more than lz4
compression = "lz4";
dnodesize = "auto";
mountpoint = "none";
normalization = "formD";
atime = "on";
relatime = "on";
# To improve performance of certain extended attributes
xattr = "sa";
"com.sun:auto-snapshot" = "false";
};
postCreateHook = ''
zfs snapshot -r rpool@blank
# zfs set keylocation="prompt" "rpool";
'';
datasets = {
# Static reservation so the pool will never be 100% full.
#
# If a pool fills up completely, delete this & reclaim space; don't
# forget to re-create it afterwards!
"reserved" = {
type = "zfs_fs";
options.canmount = "off";
options.mountpoint = "none";
options.refreservation = (lib.concatStrings [ (builtins.toString zfs_refreservationInGB) "G" ]);
options.primarycache = "none";
options.secondarycache = "none";
};
## Root system container
"nixos" = {
type = "zfs_fs";
options.mountpoint = "none";
};
## Ephemeral datasets
"nixos/local" = {
type = "zfs_fs";
options.mountpoint = "none";
};
"nixos/local/root" = {
type = "zfs_fs";
mountpoint = "/";
options.mountpoint = "legacy";
# options.mountpoint = "/";
};
"nixos/local/nix" = {
type = "zfs_fs";
mountpoint = "/nix";
options.mountpoint = "legacy";
# options.mountpoint = "/nix";
# Disable writing access time, disables if a file's access time is updated when the file is read. This can result in significant performance gains, but might confuse some software like mailers.
options.atime = "off";
options.relatime = "off";
};
"nixos/local/cache" = {
type = "zfs_fs";
mountpoint = "/cache";
options.mountpoint = "legacy";
# options.mountpoint = "/cache";
};
## Persistent datasets
"nixos/safe" = {
type = "zfs_fs";
options.mountpoint = "none";
};
"nixos/safe/home" = {
type = "zfs_fs";
mountpoint = "/home";
options.mountpoint = "legacy";
# options.mountpoint = "/home";
options."com.sun:auto-snapshot" = "true";
};
"nixos/safe/persist" = {
type = "zfs_fs";
mountpoint = "/persist";
options.mountpoint = "legacy";
# options.mountpoint = "/persist";
options."com.sun:auto-snapshot" = "true";
};
};
};
};
}