From 32a22c783d8a7c70cae3a00a27d4c0190a3accd0 Mon Sep 17 00:00:00 2001 From: Petru Paler Date: Sat, 25 Oct 2025 19:08:40 +0100 Subject: [PATCH] Set resource limits for user sessions. --- common/minimal-node.nix | 1 + common/resource-limits.nix | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 common/resource-limits.nix diff --git a/common/minimal-node.nix b/common/minimal-node.nix index dc8e902..3fd6d86 100644 --- a/common/minimal-node.nix +++ b/common/minimal-node.nix @@ -5,6 +5,7 @@ # Note: unattended-encryption is NOT included by default - add it explicitly where needed imports = [ ./impermanence.nix + ./resource-limits.nix ./sshd.nix ./user-ppetru.nix ./systemd-boot.nix diff --git a/common/resource-limits.nix b/common/resource-limits.nix new file mode 100644 index 0000000..48087ca --- /dev/null +++ b/common/resource-limits.nix @@ -0,0 +1,44 @@ +{ ... }: +{ + # Resource limits for user sessions to prevent system wedging + # + # Modern systemd/cgroups v2 approach to resource control (replaces ulimits). + # Limits apply to all user sessions (SSH, GUI, etc.) but NOT to system services. + # + # Rationale: + # - Prevents runaway user processes (nix builds, compiles, etc.) from consuming + # all resources and making the system unresponsive + # - System services (Nomad jobs, Consul, NFS, etc.) run outside user.slice and + # are unaffected by these limits + # - Ensures SSH access remains responsive even under heavy load + # + # CPU: Uses CPUWeight (not CPUQuota) so user sessions can use 100% when idle, + # but system services get priority (1.25x) during contention + # Memory: Soft limit at 90% (triggers pressure/reclaim), hard limit at 95% + # Gives 5% warning buffer before OOM kills + + systemd.slices.user = { + sliceConfig = { + # CPU weight: 80 vs default 100 for system services + # When idle: user sessions use all available CPU + # Under contention: system services get 1.25x CPU share + CPUWeight = "80"; + + # Memory soft limit: triggers reclaim and memory pressure + # User will notice slowdown but processes keep running + MemoryHigh = "90%"; + + # Memory hard limit: OOM killer targets user.slice + # 5% buffer between MemoryHigh and MemoryMax provides warning + MemoryMax = "95%"; + + # Limit number of tasks (processes/threads) + # Prevents fork bombs while still allowing nix builds + TasksMax = "4096"; + + # Lower I/O priority slightly + # System services get preference during I/O contention + IOWeight = "90"; + }; + }; +}