# Memory-pressure protection: keep the desktop alive when RAM runs out. # # A workstation that compiles from source WILL exhaust memory eventually — # a big `nix build`, a runaway eval, a browser tab. The kernel's own OOM # killer acts only after the system has thrashed itself unresponsive # (often minutes of frozen desktop) and then picks by badness score, # which can land on the compositor. # # earlyoom over systemd-oomd — a deliberate choice: oomd kills whole # cgroups, and a Hyprland session runs as ONE scope (nothing spawns # per-app systemd scopes here, unlike GNOME), so under pressure oomd # would take out the entire desktop to save it. earlyoom kills a single # process (highest oom_score ≈ the hog) BEFORE the thrash point — "kill # the build step, keep the session". nixpkgs default-enables oomd in an # inert state (no slices monitored); it's disabled outright below so # there is exactly one owner of the OOM story. { lib, ... }: { services.earlyoom = { enable = lib.mkDefault true; # Desktop toast when something is killed (relayed via # systembus-notify), so a vanished build/tab is explained rather # than mysterious. enableNotifications = lib.mkDefault true; # Never pick the session plumbing: losing the compositor or the lock # screen IS the outage this module exists to prevent (and killing a # Wayland session-lock client trips its go-to-a-tty failsafe). No # --prefer tuning: highest-memory selection already targets the hog. # Matched unanchored — NixOS wrappers rename comm to ".foo-wrapped". extraArgs = lib.mkDefault [ "--avoid" "(Hyprland|hyprlock|greetd|waybar|pipewire|wireplumber|Xwayland|nix-daemon|systemd)" ]; }; # One owner (see header): oomd ships default-on but inert; make the # earlyoom choice explicit and total. systemd.oomd.enable = lib.mkDefault false; }