1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.icecream.daemon;
7in {
8
9 ###### interface
10
11 options = {
12
13 services.icecream.daemon = {
14
15 enable = mkEnableOption (lib.mdDoc "Icecream Daemon");
16
17 openFirewall = mkOption {
18 type = types.bool;
19 description = lib.mdDoc ''
20 Whether to automatically open receive port in the firewall.
21 '';
22 };
23
24 openBroadcast = mkOption {
25 type = types.bool;
26 description = lib.mdDoc ''
27 Whether to automatically open the firewall for scheduler discovery.
28 '';
29 };
30
31 cacheLimit = mkOption {
32 type = types.ints.u16;
33 default = 256;
34 description = lib.mdDoc ''
35 Maximum size in Megabytes of cache used to store compile environments of compile clients.
36 '';
37 };
38
39 netName = mkOption {
40 type = types.str;
41 default = "ICECREAM";
42 description = lib.mdDoc ''
43 Network name to connect to. A scheduler with the same name needs to be running.
44 '';
45 };
46
47 noRemote = mkOption {
48 type = types.bool;
49 default = false;
50 description = lib.mdDoc ''
51 Prevent jobs from other nodes being scheduled on this daemon.
52 '';
53 };
54
55 schedulerHost = mkOption {
56 type = types.nullOr types.str;
57 default = null;
58 description = lib.mdDoc ''
59 Explicit scheduler hostname, useful in firewalled environments.
60
61 Uses scheduler autodiscovery via broadcast if set to null.
62 '';
63 };
64
65 maxProcesses = mkOption {
66 type = types.nullOr types.ints.u16;
67 default = null;
68 description = lib.mdDoc ''
69 Maximum number of compile jobs started in parallel for this daemon.
70
71 Uses the number of CPUs if set to null.
72 '';
73 };
74
75 nice = mkOption {
76 type = types.int;
77 default = 5;
78 description = lib.mdDoc ''
79 The level of niceness to use.
80 '';
81 };
82
83 hostname = mkOption {
84 type = types.nullOr types.str;
85 default = null;
86 description = lib.mdDoc ''
87 Hostname of the daemon in the icecream infrastructure.
88
89 Uses the hostname retrieved via uname if set to null.
90 '';
91 };
92
93 user = mkOption {
94 type = types.str;
95 default = "icecc";
96 description = lib.mdDoc ''
97 User to run the icecream daemon as. Set to root to enable receive of
98 remote compile environments.
99 '';
100 };
101
102 package = mkOption {
103 default = pkgs.icecream;
104 defaultText = literalExpression "pkgs.icecream";
105 type = types.package;
106 description = lib.mdDoc "Icecream package to use.";
107 };
108
109 extraArgs = mkOption {
110 type = types.listOf types.str;
111 default = [];
112 description = lib.mdDoc "Additional command line parameters.";
113 example = [ "-v" ];
114 };
115 };
116 };
117
118 ###### implementation
119
120 config = mkIf cfg.enable {
121 networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ 10245 ];
122 networking.firewall.allowedUDPPorts = mkIf cfg.openBroadcast [ 8765 ];
123
124 systemd.services.icecc-daemon = {
125 description = "Icecream compile daemon";
126 after = [ "network.target" ];
127 wantedBy = [ "multi-user.target" ];
128
129 serviceConfig = {
130 ExecStart = escapeShellArgs ([
131 "${getBin cfg.package}/bin/iceccd"
132 "-b" "$STATE_DIRECTORY"
133 "-u" "icecc"
134 (toString cfg.nice)
135 ]
136 ++ optionals (cfg.schedulerHost != null) ["-s" cfg.schedulerHost]
137 ++ optionals (cfg.netName != null) [ "-n" cfg.netName ]
138 ++ optionals (cfg.cacheLimit != null) [ "--cache-limit" (toString cfg.cacheLimit) ]
139 ++ optionals (cfg.maxProcesses != null) [ "-m" (toString cfg.maxProcesses) ]
140 ++ optionals (cfg.hostname != null) [ "-N" (cfg.hostname) ]
141 ++ optional cfg.noRemote "--no-remote"
142 ++ cfg.extraArgs);
143 DynamicUser = true;
144 User = "icecc";
145 Group = "icecc";
146 StateDirectory = "icecc";
147 RuntimeDirectory = "icecc";
148 AmbientCapabilities = "CAP_SYS_CHROOT";
149 CapabilityBoundingSet = "CAP_SYS_CHROOT";
150 };
151 };
152 };
153
154 meta.maintainers = with lib.maintainers; [ emantor ];
155}