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