feat(stability): default-on memory-pressure protection (earlyoom)
Some checks failed
Check / eval (push) Has been cancelled

modules/nixos/oom.nix — running out of memory now kills the offending
process (with a desktop notification via systembus-notify) instead of
freezing the desktop for minutes until the kernel OOM killer fires.

earlyoom over systemd-oomd, deliberately: oomd kills whole cgroups,
and a Hyprland session runs as ONE scope (nothing here spawns per-app
systemd scopes, unlike GNOME) — under pressure oomd would take out the
entire desktop to save it. earlyoom kills the single largest process
before the thrash point. nixpkgs default-enables oomd in an inert
state (no slices monitored); it is disabled outright so there is one
owner. Session plumbing is --avoid-listed (unanchored — NixOS wrappers
rename comm to .foo-wrapped); no --prefer tuning, largest-RSS
selection already finds the hog. All mkDefault; opt out with
services.earlyoom.enable = false (README note added).

Verified: V0 (flake check) + V2 — new checks.oom-protection
runNixOSTest, executed: a chunked allocator (686 MB peak, 1 GB VM) is
SIGTERM'd by earlyoom in 0.1 s, a bystander unit survives (the
process-level granularity the module exists for), and systemd-oomd is
asserted inactive. 25 s runtime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-07-04 09:45:21 +01:00
parent 938753273d
commit 5ea4f0c9ac
7 changed files with 133 additions and 17 deletions

View File

@@ -35,19 +35,6 @@ likely failure mode; the legacy repo OOM'd on heavy evals). **Stretch
`nix-kvm`, host mode) unlocks the workflow's commented `vm-checks` job
— the VM suite + real builds in CI (upgrades half of item 14 free).
### 3. Memory-pressure protection (no more frozen desktops)
New. A workstation that compiles from source *will* hit memory
exhaustion (the discarded release bump died to a Hyprland OOM; a big
`nix build` can freeze the session today — nothing mitigates OOM).
Ship a default-on userspace OOM killer: pick `systemd-oomd`
(`systemd.oomd` + the NixOS enables for user slices) or `earlyoom`
write the choice + rationale into the commit; consider protecting the
session (Hyprland/greetd) and sacrificing `nix-daemon` build slices
first. **Why:** "rock-stable" means the UI never locks up. **Done
when:** on by default (`lib.mkDefault`), overridable natively; the
choice documented in README's "beyond the surface" note. **Verify:**
V2 — a VM check that memory pressure kills the hog, not the session.
### 4. btrfs-assistant segfault — attempt the nixpkgs override fix
ROADMAP § Snapshot browse/restore. btrfs-assistant 2.2 crashes in
`libbtrfsutil.so.1.4.0` (ABI mismatch, confirmed not a VM artifact); the

View File

@@ -17,6 +17,24 @@ Template:
---
## 2026-07-04 — Memory-pressure protection shipped (loop iteration #3)
- **Task:** BACKLOG NOW#3 — default-on userspace OOM killer.
- **Did:** `modules/nixos/oom.nix`: earlyoom (mkDefault on, desktop
notifications, session-plumbing `--avoid` list, no `--prefer`) +
`systemd.oomd.enable = false`. Choice rationale: Hyprland session is
one cgroup scope → oomd's cgroup-level kill would nuke the desktop;
earlyoom is process-level. Found en route: nixpkgs default-enables
oomd *inert* (enable=true, all slice toggles false). README "beyond
the surface" note added.
- **Verified:** V0 (flake check) + **V2** — new `checks.oom-protection`
runNixOSTest, run for real: hog (chunked allocator, 686 MB peak in a
1 GB VM) SIGTERM'd by earlyoom in 0.1 s, bystander unit survived,
oomd asserted inactive. 25 s test, cheap enough for the suite.
- **Pending:** nothing hardware-specific (behavior fully VM-provable).
- **Next suggestion:** NOW#4 (btrfs-assistant override attempt). Also:
CI run #58 (the .gitea fix) was *running* at commit time — check its
outcome next tick; this push triggers #59.
## 2026-07-04 — CI fix: wrong workflow dir (correction to iteration #2)
- **Task:** Bernardo reported no run despite an active runner + shared
his compose file: the server is **Gitea** (gitea/act_runner), not