1{ config, lib, ... }: let
2
3 cfg = config.systemd.oomd;
4
5in {
6 options.systemd.oomd = {
7 enable = lib.mkEnableOption (lib.mdDoc "the `systemd-oomd` OOM killer") // { default = true; };
8
9 # Fedora enables the first and third option by default. See the 10-oomd-* files here:
10 # https://src.fedoraproject.org/rpms/systemd/tree/acb90c49c42276b06375a66c73673ac351025597
11 enableRootSlice = lib.mkEnableOption (lib.mdDoc "oomd on the root slice (`-.slice`)");
12 enableSystemSlice = lib.mkEnableOption (lib.mdDoc "oomd on the system slice (`system.slice`)");
13 enableUserServices = lib.mkEnableOption (lib.mdDoc "oomd on all user services (`user@.service`)");
14
15 extraConfig = lib.mkOption {
16 type = with lib.types; attrsOf (oneOf [ str int bool ]);
17 default = {};
18 example = lib.literalExpression ''{ DefaultMemoryPressureDurationSec = "20s"; }'';
19 description = lib.mdDoc ''
20 Extra config options for `systemd-oomd`. See {command}`man oomd.conf`
21 for available options.
22 '';
23 };
24 };
25
26 config = lib.mkIf cfg.enable {
27 systemd.additionalUpstreamSystemUnits = [
28 "systemd-oomd.service"
29 "systemd-oomd.socket"
30 ];
31 systemd.services.systemd-oomd.wantedBy = [ "multi-user.target" ];
32
33 environment.etc."systemd/oomd.conf".text = lib.generators.toINI {} {
34 OOM = cfg.extraConfig;
35 };
36
37 systemd.oomd.extraConfig.DefaultMemoryPressureDurationSec = lib.mkDefault "20s"; # Fedora default
38
39 users.users.systemd-oom = {
40 description = "systemd-oomd service user";
41 group = "systemd-oom";
42 isSystemUser = true;
43 };
44 users.groups.systemd-oom = { };
45
46 systemd.slices."-".sliceConfig = lib.mkIf cfg.enableRootSlice {
47 ManagedOOMSwap = "kill";
48 };
49 systemd.slices."system".sliceConfig = lib.mkIf cfg.enableSystemSlice {
50 ManagedOOMSwap = "kill";
51 };
52 systemd.services."user@".serviceConfig = lib.mkIf cfg.enableUserServices {
53 ManagedOOMMemoryPressure = "kill";
54 ManagedOOMMemoryPressureLimit = "50%";
55 };
56 };
57}