# vim: ts=2 { config, lib, pkgs, ... }: let cfg = config.system.fileSystemLayouts; defaultMountOptions = [ "compress-force=zstd:15" # This saves disk space, at a performance cost "noatime" # should have some performance upsides, and I don't use it anyways "lazytime" # make time changes in memory ]; in { options.system.fileSystemLayouts = { enable = lib.mkEnableOption (lib.mdDoc "fileSystemLayout"); mainDisk = lib.mkOption { type = lib.types.path; example = lib.literalExpression "/dev/disk/by-uuid/0442cb6d-f13a-4635-b487-fa76189774c5"; description = lib.mdDoc "Path to the main disk"; }; efiDisk = lib.mkOption { type = lib.types.path; example = lib.literalExpression "/dev/disk/by-uuid/5143-6136"; description = lib.mdDoc "Path to the main disk"; }; ssd = lib.mkOption { type = lib.types.bool; example = lib.literalExpression "true"; default = false; description = lib.mdDoc "Enable ssd specific improvements?"; }; swap = { uuid = lib.mkOption { type = lib.types.str; example = lib.literalExpression "d1d20ae7-3d8a-44da-86da-677dbbb10c89"; description = lib.mdDoc "The uuid of the swapfile"; }; resumeOffset = lib.mkOption { type = lib.types.str; example = lib.literalExpression "134324224"; description = lib.mdDoc "The resume offset of the swapfile"; }; }; }; config = lib.mkIf cfg.enable { systemd = { services = { hibernate-preparation = { # TODO check if they work wantedBy = ["systemd-hibernate.service"]; unitConfig = { Description = "Enable swap file and disable zram before hibernate"; Before = "systemd-hibernate.service"; }; serviceConfig = { Type = "oneshot"; User = "root"; ExecStart = "${pkgs.dash}/bin/dash -c \"${pkgs.util-linux}/bin/swapon /swap/swapfile && ${pkgs.util-linux}/bin/swapoff /dev/zram0\""; }; }; hibernate-resume = { wantedBy = ["hibernate.target"]; unitConfig = { Description = "Disable swap after resuming from hibernation"; After = "hibernate.target"; }; serviceConfig = { Type = "oneshot"; User = "root"; ExecStart = "${pkgs.util-linux}/bin/swapoff /swap/swapfile"; }; }; systemd-hibernate.serviceConfig.Environment = "SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1"; systemd-logind.serviceConfig.Environment = "SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1"; }; timers.fstrim = lib.mkIf cfg.ssd { wantedBy = ["timers.target"]; wants = ["fstrim.service"]; unitConfig = { Description = "Discard unused blocks once a week"; Documentation = "man:fstrim"; ConditionVirtualization = "!container"; ConditionPathExists = "!/etc/initrd-release"; }; timerConfig = { OnCalendar = "weekly"; AccuracySec = "1h"; Persistent = "true"; RandomizedDelaySec = "6000"; }; }; services.fstrim = lib.mkIf cfg.ssd { wantedBy = lib.mkForce []; unitConfig = { Description = "Discard unused blocks on filesystems from /etc/fstab"; Documentation = "man:fstrim(8)"; ConditionVirtualization = "!container"; }; serviceConfig = { Type = "oneshot"; ExecStart = "${pkgs.util-linux}/bin/fstrim --listed-in /etc/fstab:/proc/self/mountinfo --verbose --quiet-unsupported"; PrivateDevices = "no"; PrivateNetwork = "yes"; PrivateUsers = "no"; ProtectKernelTunables = "yes"; ProtectKernelModules = "yes"; ProtectControlGroups = "yes"; MemoryDenyWriteExecute = "yes"; SystemCallFilter = "@default @file-system @basic-io @system-service"; }; }; }; fileSystems = { "/" = { device = "none"; fsType = "tmpfs"; options = ["defaults" "size=4G" "mode=755"]; }; "/nix" = { device = cfg.mainDisk; fsType = "btrfs"; options = ["subvol=nix-store"] ++ defaultMountOptions; }; "/srv" = { device = cfg.mainDisk; fsType = "btrfs"; neededForBoot = true; options = ["subvol=persistent-storage"] ++ defaultMountOptions; }; "/swap" = { device = cfg.mainDisk; fsType = "btrfs"; neededForBoot = true; options = ["subvol=swap"] ++ defaultMountOptions; }; "/boot" = { device = cfg.efiDisk; fsType = "vfat"; }; }; swapDevices = []; zramSwap = { enable = true; priority = 10; # needs to be higher than harware-swap }; boot.kernelParams = [ "resume=UUID=${cfg.swap.uuid}" "resume_offset=${cfg.swap.resumeOffset}" "zswap.enabled=0" # zswap and zram are not really compatible ]; }; }