nohang: init at 0.2.0, nixos/nohang: init (#409254)
This commit is contained in:
@@ -6484,6 +6484,11 @@
|
||||
}
|
||||
];
|
||||
};
|
||||
Dev380 = {
|
||||
name = "Dev380";
|
||||
github = "Dev380";
|
||||
githubId = 49997896;
|
||||
};
|
||||
developer-guy = {
|
||||
name = "Batuhan Apaydın";
|
||||
email = "developerguyn@gmail.com";
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -1532,6 +1532,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
|
||||
|
||||
@@ -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 { };
|
||||
|
||||
@@ -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")
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
nixosTests,
|
||||
fetchFromGitHub,
|
||||
python3,
|
||||
sudo,
|
||||
libnotify,
|
||||
coreutils,
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "nohang";
|
||||
version = "0.2.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "hakavlad";
|
||||
repo = "nohang";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-aRiBGnJHdtQ5euvJ4DSuCZO5i5OJVRiCesaatrIARmg=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
patchShebangs src
|
||||
substituteInPlace src/nohang \
|
||||
--replace-fail 'notify-send' '${lib.getExe libnotify}' \
|
||||
--replace-fail 'sudo' '${lib.getExe sudo}' \
|
||||
--replace-fail "'env'" "'${lib.getExe' coreutils "env"}'"
|
||||
'';
|
||||
|
||||
buildInputs = [ python3 ];
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
installTargets = [ "base" ];
|
||||
installFlags = [
|
||||
"DESTDIR=${placeholder "out"}"
|
||||
"PREFIX=/"
|
||||
"SBINDIR=/sbin"
|
||||
"SYSCONFDIR=/etc"
|
||||
"SYSTEMDUNITDIR=/lib/systemd/system"
|
||||
];
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) nohang;
|
||||
};
|
||||
|
||||
meta = {
|
||||
homepage = "https://github.com/hakavlad/nohang";
|
||||
description = "Sophisticated low memory handler for Linux";
|
||||
license = with lib.licenses; [ mit ];
|
||||
mainProgram = "nohang";
|
||||
platforms = lib.platforms.linux;
|
||||
maintainers = with lib.maintainers; [ Dev380 ];
|
||||
};
|
||||
})
|
||||
Reference in New Issue
Block a user