ram-sentinel

Crates.ioram-sentinel
lib.rsram-sentinel
version0.1.4
created_at2025-12-13 15:20:14.687754+00
updated_at2025-12-17 07:50:23.945924+00
descriptionA surgical OOM prevention daemon for Linux desktops. Configurably monitors RAM, swap, and/or PSI (Pressure Stall Information) to selectively kill low-priority processes (e.g., browser tabs) before the system freezes.
homepagehttps://github.com/benedictjohannes/ram-sentinel
repositoryhttps://github.com/benedictjohannes/ram-sentinel
max_upload_size
id1983041
size142,306
(benedictjohannes)

documentation

https://docs.rs/ram-sentinel

README

RAM Sentinel 🛡️

🚧 Pre-release — Contributions and Feedback welcome!

The Surgical Memory Guardian for Linux Desktops.

Stop nuking my entire browser just because I'm opening too many tabs!

Build Status Crates.io License: MIT 

ram-sentinel is a userspace OOM (Out-of-Memory) prevention daemon designed specifically for modern workstations. Unlike earlyoom or nohang which often act as blunt instruments (killing your heaviest app, usually your Browser or IDE), ram-sentinel uses Surgical Cmdline Process Targeting and Pressure Stall Information (PSI) to surgically remove specific low-value targets (like browser renderer tabs) before threatening your main workflow.

It runs as a standard user (systemd --user), requires no root privileges, and talks to you via desktop notifications. In my desktop, it takes up <5MB RSS.

🚀 Why You Need This

If you are tired of your system freezing for 30 seconds before suddenly closing your entire game or browser, this tool is for you.

Feature Standard OOM Killer (systemd-oomd) RAM Sentinel
Targeting Kills the parent process (Largest RSS). Bye bye Browser. Targeted snipe. Kills type=renderer tabs first. Keeps Browser alive.
Trigger RAM Full (Too late) or blunt heuristic. PSI (Pressure): Acts when system stutters, not just when full.
Safety Can kill PID that was just reused (Race condition). PID Identity Check: Verifies process start time before killing.
UX Silent death. Notifications: Warns you before killing. Tells you what it killed.
Permissions Root required. Userspace: Runs as YOU.

⚡ Quick Start (Sane Defaults)

You don't have to configure anything to get started. ram-sentinel ships with Sane Defaults that work for 99% of desktop users.

Installation

cargo install ram-sentinel

Run immediately

ram-sentinel

Enable as a Service (Recommended)

Generate a systemd unit and enable it:

# Preview the unit file 
ram-sentinel --print-systemd-user-unit

# Install and Enable
mkdir -p ~/.config/systemd/user/
ram-sentinel --print-systemd-user-unit ~/.config/systemd/user/ram-sentinel.service
# edit if necessary
systemctl --user daemon-reload
systemctl --user enable --now ram-sentinel

⚙️ Configuration

ram-sentinel looks for a config file in $XDG_CONFIG_HOME/ram-sentinel.yaml (usually ~/.config/ram-sentinel.yaml).

🌟 Recommended Configuration

Use this if you want the "Anti-Freeze" experience. This enables the PSI monitor to kill runaway processes when the system starts thrashing (lagging), even if you technically have free RAM.

ram:
  warnMinFreeBytes: 500M
  # Safety net: Kill if RAM drops below 5%
  killMinFreePercent: 5.0 
psi:
  # Warn when system feels "heavy" (stuttering)
  warnMaxPercent: 40.0
  # EMERGENCY: Kill when system freezes (mouse lag/thrashing)
  killMaxPercent: 85.0
  amountToFree: 400M
checkIntervalMs: 1000
warnResetMs: 30000
sigtermWaitMs: 2500
ignoreNames:
  # Broad matches to protect your shell/environment
  - kwin
  - plasma
  - gnome-shell
  - sshd
killTargets:
  # TIER 1 PRIORITY: The Expendables
  # These are killed FIRST.
  - type=renderer       # Chrome/Electron tabs
  - -contentproc        # Firefox tabs
  - ^/usr/bin/node      # Strict prefix match for processes you want to target first, e.g. for local node scripts
killStrategy: highestOomScore

Sane Defaults 🛡️

If no config file is found, ram-sentinel loads this configuration automatically. It is conservative and focuses on preventing hard lockups.

ram:
  warnMinFreePercent: 10.0
  killMinFreePercent: 5.0
psi: {} # PSI disabled by default to be safe
checkIntervalMs: 1000
warnResetMs: 30000
sigtermWaitMs: 5000
killTargets:
  - type=renderer
  - -contentproc
ignoreNames: []
killStrategy: highestOomScore

📖 Full Configuration Reference

Detailed explanation of every available option.

# --- RAM LIMITS ---
# Triggers if Available RAM falls below these values.
# NOTE: If 'Bytes' is set, it OVERRIDES 'Percent'.
ram:
  warnMinFreeBytes: 1G      # Warn if < 1GB free
  warnMinFreePercent: 10.0  # (Ignored if Bytes is set)
  killMinFreeBytes: 250M    # Kill if < 250MB free
  killMinFreePercent: 5.0   # (Ignored if Bytes is set)

# --- SWAP LIMITS ---
# Same logic as RAM.
swap:
  warnMinFreePercent: 20.0
  killMinFreePercent: 5.0

# --- PSI (PRESSURE STALL INFORMATION) ---
# Requires Linux Kernel 4.20+ with CONFIG_PSI=y
# "Pressure" = % of time tasks are stalled waiting for memory.
psi:
  warnMaxPercent: 40.0      # Warn if system is stuttering (40% pressure)
  killMaxPercent: 90.0      # Kill if system is frozen (90% pressure)
  amountToFree: 500M        # If triggered, kill processes until 500MB is freed

# --- TIMING ---
checkIntervalMs: 1000       # How often to poll system stats
warnResetMs: 30000          # Don't spam notifications more than every 30s
sigtermWaitMs: 3000         # Wait 3s after SIGTERM before sending SIGKILL

# --- TARGETING STRATEGY ---
# 1. Regex: "/pattern/" matches Name or Command Line
# 2. Prefix: "^string" matches START of Command Line
# 3. Literal: "string" matches substring of Name
killTargets:
  - type=renderer           # Priority 1: Browser tabs
  - /npm start/             # Priority 2: NPM scripts
  - ^/usr/bin/python        # Priority 3: Python scripts

ignoreNames:
  - ^Xorg                   # Never kill Xorg
  - /wayland/               # Never kill Wayland compositors

# Strategies: 'highestOomScore' (recommended) or 'largestRss'
killStrategy: highestOomScore

🧠 Design Philosophy

ram-sentinel is built on the Safety First doctrine.

  1. Priority Queues: We define a priority system for processes. killTargets are "Second Class Citizens"—they are always sacrificed first. Your main apps are only touched if shedding the expendables didn't solve the memory crisis.
  2. Identity Verification: Before sending the final SIGKILL, the sentinel verifies that the PID's create_time matches the victim it selected 3 seconds ago. This prevents the "PID Reuse" race condition where a guardian accidentally kills a brand new process that grabbed the dead victim's PID.
  3. Strict Override: Configuration follows a "Manual Override" logic. If you set a specific Byte limit (500MB), the vague Percentage limit (5%) is ignored. You get exactly what you ask for.

ram-sentinel is heavily inspired by the excellent earlyoom, implementing many features I wished it had (like surgical process targeting and fine grained tuning). For a deeper dive into the architectural decisions, see GEMINI.md.

Roadmap

We're in the exciting early phase. I've used ram-sentinel on my CachyOS KDE desktop myself and it appears to be solid. But expect refinements and breaking changes before 1.0.

Feedback, issues, and PRs are very welcome! Contributors wanted. 👋

1. Comprehensive Integration Testing Framework

We deliberately skip traditional unit tests—mocking the wild west of /proc, PSI, and real-world process chaos just breeds false confidence.

Instead, we're building a full end-to-end behavioral testing suite:

  • Runs the exact release binaries in a clean, reproducible environment (e.g., a minimal Ubuntu VM via virsh with 2 CPUs / 4GB RAM—the perfect choke point).
  • Includes a coordinator to orchestrate scenarios and a troublemaker to simulate realistic culprits (sleeping renderer tabs, RAM-hungry spikes, mixed workloads).
  • Parses structured logs, monitors live PSI/meminfo, and asserts surgical precision: "Did it snipe only the lazy tabs without touching the IDE?"

This gives us rock-solid, real-world proof that ram-sentinel delivers on its promises—no hype, just results. Conceptual details in TestingFramework.md.

2. Full System-Level Daemon Mode

Once the testing framework is battle-hardened, we'll expand beyond userspace:

  • Optional root mode as a proper system service.
  • New CLI flag: --listen [socket-path] for the userspace daemon - lets the root daemon push notifications to your user session (so desktop pop-ups still work seamlessly).
  • Cgroup v2 awareness: Layer surgical targeting on top of cgroup pressure metrics for better scoping in containerized/mixed setups. Inspired by tools like systemd-oomd—thanks for the blueprint!

The goal? Make ram-sentinel the go-to guardian for all things Linux: desktops, workstations, and servers. Okay, well, maybe not Android 😖

Commit count: 0

cargo fmt