mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-06-05 21:03:40 +00:00
nixos/nohang: init module
nixosTests.nohang: init These tests are modified from earlyoom's tests. It tries to OOM the test VM and then check that nohang's output is as expected. Unlike the earlyoom test, we use the default config, so we test for whether the signal nohang set was SIGKILL or SIGTERM and adjust the output checking accordingly nohang: add linked test for the nixos module nixos/doc/rl-2511: init nohang nixos/nohang: change option name to configPath nixos/nohang: use lib.getExe instead of interpolation Co-authored-by: Leah Amelia Chen <github@acc.pluie.me> nixos/nohang: use lib.getExe "tail" instead Co-authored-by: Leah Amelia Chen <github@acc.pluie.me> nixosTests.nohang: switch to runTest nixos/nohang: use multiline string for CapabilityBoundingSet in service config Co-authored-by: Sandro <sandro.jaeckel@gmail.com> nohang: fix whitespace formatting
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
|
||||
- [LibreChat](https://www.librechat.ai/), open-source self-hostable ChatGPT clone with Agents and RAG APIs. Available as [services.librechat](#opt-services.librechat.enable).
|
||||
|
||||
- [nohang](https://github.com/hakavlad/nohang), a daemon for Linux that prevents out of memory (OOM) situations from affecting system responsiveness. Available as [services.nohang](#opt-services.nohang.enable)
|
||||
|
||||
- [DankMaterialShell](https://danklinux.com), a complete desktop shell for Wayland compositors built with Quickshell. Available as [programs.dms-shell](#opt-programs.dms-shell.enable).
|
||||
|
||||
- [dms-greeter](https://danklinux.com), a modern display manager greeter for DankMaterialShell that works with greetd and supports multiple Wayland compositors. Available as [services.displayManager.dms-greeter](#opt-services.displayManager.dms-greeter.enable).
|
||||
|
||||
@@ -1530,6 +1530,7 @@
|
||||
./services/system/localtimed.nix
|
||||
./services/system/nix-daemon-firewall.nix
|
||||
./services/system/nix-daemon.nix
|
||||
./services/system/nohang.nix
|
||||
./services/system/nscd.nix
|
||||
./services/system/nvme-rs.nix
|
||||
./services/system/saslauthd.nix
|
||||
|
||||
113
nixos/modules/services/system/nohang.nix
Normal file
113
nixos/modules/services/system/nohang.nix
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.nohang;
|
||||
|
||||
inherit (lib)
|
||||
literalExpression
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
types
|
||||
;
|
||||
in
|
||||
{
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [ Dev380 ];
|
||||
};
|
||||
|
||||
options.services.nohang = {
|
||||
enable = mkEnableOption "nohang, a daemon that keeps system responsiveness when Linux is out of memory";
|
||||
|
||||
package = mkPackageOption pkgs "nohang" { };
|
||||
|
||||
configPath = mkOption {
|
||||
type = types.either (types.enum [
|
||||
"basic"
|
||||
"desktop"
|
||||
]) types.path;
|
||||
default = "desktop";
|
||||
example = literalExpression "./my-nohang-config.conf";
|
||||
description = ''
|
||||
Configuration file to use with nohang. The default and desktop example configurations in the nohang repository
|
||||
can be used by setting this to "basic" or "desktop" (which is the default). Otherwise, you can set it to the path
|
||||
of a custom configuration file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.nohang = {
|
||||
description = "Sophisticated low memory handler";
|
||||
documentation = [
|
||||
"man:nohang(8)"
|
||||
"https://github.com/hakavlad/nohang"
|
||||
];
|
||||
after = [ "sysinit.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart =
|
||||
"${lib.getExe cfg.package} --monitor --config "
|
||||
+ (
|
||||
if cfg.configPath == "basic" then
|
||||
"${cfg.package}/etc/nohang/nohang.conf"
|
||||
else if cfg.configPath == "desktop" then
|
||||
"${cfg.package}/etc/nohang/nohang-desktop.conf"
|
||||
else
|
||||
cfg.configPath
|
||||
);
|
||||
Slice = "hostcritical.slice";
|
||||
SyslogIdentifier =
|
||||
if cfg.configPath == "basic" then
|
||||
"nohang"
|
||||
else if cfg.configPath == "desktop" then
|
||||
"nohang-desktop"
|
||||
else
|
||||
"nohang-custom-config";
|
||||
KillMode = "mixed";
|
||||
Restart = "always";
|
||||
RestartSec = 0;
|
||||
|
||||
CPUSchedulingResetOnFork = true;
|
||||
RestrictRealtime = "yes";
|
||||
|
||||
TasksMax = 25;
|
||||
MemoryMax = "100M";
|
||||
MemorySwapMax = "100M";
|
||||
|
||||
UMask = 27;
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = "/var/log";
|
||||
InaccessiblePaths = "/home /root";
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHostname = true;
|
||||
MemoryDenyWriteExecute = "yes";
|
||||
RestrictNamespaces = "yes";
|
||||
LockPersonality = "yes";
|
||||
PrivateTmp = true;
|
||||
DeviceAllow = "/dev/kmsg rw";
|
||||
DevicePolicy = "closed";
|
||||
|
||||
CapabilityBoundingSet = [
|
||||
"CAP_KILL"
|
||||
"CAP_IPC_LOCK"
|
||||
"CAP_SYS_PTRACE"
|
||||
"CAP_DAC_READ_SEARCH"
|
||||
"CAP_DAC_OVERRIDE"
|
||||
"CAP_AUDIT_WRITE"
|
||||
"CAP_SETUID"
|
||||
"CAP_SETGID"
|
||||
"CAP_SYS_RESOURCE"
|
||||
"CAP_SYSLOG"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1105,6 +1105,7 @@ in
|
||||
nixpkgs = pkgs.callPackage ../modules/misc/nixpkgs/test.nix { inherit evalMinimalConfig; };
|
||||
nixseparatedebuginfod2 = runTest ./nixseparatedebuginfod2.nix;
|
||||
node-red = runTest ./node-red.nix;
|
||||
nohang = runTest ./nohang.nix;
|
||||
nomad = runTest ./nomad.nix;
|
||||
nominatim = runTest ./nominatim.nix;
|
||||
non-default-filesystems = handleTest ./non-default-filesystems.nix { };
|
||||
|
||||
56
nixos/tests/nohang.nix
Normal file
56
nixos/tests/nohang.nix
Normal file
@@ -0,0 +1,56 @@
|
||||
# The following was modified from ./earlyoom.nix
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
name = "nohang";
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [
|
||||
Dev380
|
||||
];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
# Limit VM resource usage.
|
||||
virtualisation.memorySize = 1024;
|
||||
|
||||
services.nohang.enable = true;
|
||||
# disable other oom killers just in case
|
||||
systemd.oomd.enable = false;
|
||||
|
||||
systemd.services.testbloat = {
|
||||
description = "Create a lot of memory pressure";
|
||||
serviceConfig = {
|
||||
ExecStart = "${lib.getExe' pkgs.coreutils "tail"} /dev/zero";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# SIGTERM may be given so tail /dev/zero may or may not succeed
|
||||
# The output will have have something like "Sending SIGTERM to /nix/store/87fc"
|
||||
# with the truncated path so we'll check for that in the test
|
||||
testScript = ''
|
||||
machine.wait_for_unit("nohang.service")
|
||||
|
||||
with subtest("nohang should kill the bad service"):
|
||||
machine.execute("systemctl start --wait testbloat.service")
|
||||
signal_type = None
|
||||
match machine.get_unit_info("testbloat.service")["Result"]:
|
||||
case "signal":
|
||||
signal_type = "SIGKILL"
|
||||
case "success":
|
||||
signal_type = "SIGTERM"
|
||||
output = machine.succeed('journalctl -u nohang.service -b0')
|
||||
|
||||
if not f'[ OK ] Sending {signal_type}' in output:
|
||||
raise Exception(f"'[ OK ] Sending {signal_type}' not in output")
|
||||
if not 'The victim' in output:
|
||||
raise Exception("'The victim' not in output")
|
||||
if not 'Memory status after implementing a corrective action:' in output:
|
||||
raise Exception("'Memory status after implementing a corrective action:' not in output")
|
||||
if not 'FINISHING implement_corrective_action()' in output:
|
||||
raise Exception("'FINISHING implement_corrective_action()' not in output")
|
||||
if not f"{signal_type} to {'${pkgs.coreutils}'[:len('/nix/store/1234')]}: 1" in output:
|
||||
raise Exception(f"'{signal_type} to {'${pkgs.coreutils}'[:len('/nix/store/1234')]}: 1' not in output")
|
||||
'';
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
nixosTests,
|
||||
fetchFromGitHub,
|
||||
python3,
|
||||
sudo,
|
||||
@@ -39,6 +40,10 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
"SYSTEMDUNITDIR=/lib/systemd/system"
|
||||
];
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) nohang;
|
||||
};
|
||||
|
||||
meta = {
|
||||
homepage = "https://github.com/hakavlad/nohang";
|
||||
description = "Sophisticated low memory handler for Linux";
|
||||
|
||||
Reference in New Issue
Block a user