1{ lib
2, pkgs
3, config
4, options
5, ...
6}:
7let
8 cfg = config.programs.benchexec;
9 opt = options.programs.benchexec;
10
11 filterUsers = x:
12 if builtins.isString x then config.users.users ? ${x} else
13 if builtins.isInt x then x else
14 throw "filterUsers expects string (username) or int (UID)";
15
16 uid = x:
17 if builtins.isString x then config.users.users.${x}.uid else
18 if builtins.isInt x then x else
19 throw "uid expects string (username) or int (UID)";
20in
21{
22 options.programs.benchexec = {
23 enable = lib.mkEnableOption "BenchExec";
24 package = lib.options.mkPackageOption pkgs "benchexec" { };
25
26 users = lib.options.mkOption {
27 type = with lib.types; listOf (either str int);
28 description = ''
29 Users that intend to use BenchExec.
30 Provide usernames of users that are configured via {option}`${options.users.users}` as string,
31 and UIDs of "mutable users" as integers.
32 Control group delegation will be configured via systemd.
33 For more information, see <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#setting-up-cgroups>.
34 '';
35 default = [ ];
36 example = lib.literalExpression ''
37 [
38 "alice" # username of a user configured via ${options.users.users}
39 1007 # UID of a mutable user
40 ]
41 '';
42 };
43 };
44
45 config = lib.mkIf cfg.enable {
46 assertions = (map
47 (user: {
48 assertion = config.users.users ? ${user};
49 message = ''
50 The user '${user}' intends to use BenchExec (via `${opt.users}`), but is not configured via `${options.users.users}`.
51 '';
52 })
53 (builtins.filter builtins.isString cfg.users)
54 ) ++ (map
55 (id: {
56 assertion = config.users.mutableUsers;
57 message = ''
58 The user with UID '${id}' intends to use BenchExec (via `${opt.users}`), but mutable users are disabled via `${options.users.mutableUsers}`.
59 '';
60 })
61 (builtins.filter builtins.isInt cfg.users)
62 ) ++ [
63 {
64 assertion = config.systemd.enableUnifiedCgroupHierarchy == true;
65 message = ''
66 The BenchExec module `${opt.enable}` only supports control groups 2 (`${options.systemd.enableUnifiedCgroupHierarchy} = true`).
67 '';
68 }
69 ];
70
71 environment.systemPackages = [ cfg.package ];
72
73 # See <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#setting-up-cgroups>.
74 systemd.services = builtins.listToAttrs (map
75 (user: {
76 name = "user@${builtins.toString (uid user)}";
77 value = {
78 serviceConfig.Delegate = "yes";
79 overrideStrategy = "asDropin";
80 };
81 })
82 (builtins.filter filterUsers cfg.users));
83
84 # See <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#requirements>.
85 virtualisation.lxc.lxcfs.enable = lib.mkDefault true;
86
87 # See <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#requirements>.
88 programs = {
89 cpu-energy-meter.enable = lib.mkDefault true;
90 pqos-wrapper.enable = lib.mkDefault true;
91 };
92
93 # See <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#kernel-requirements>.
94 security.unprivilegedUsernsClone = true;
95 };
96
97 meta.maintainers = with lib.maintainers; [ lorenzleutgeb ];
98}