1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.distccd;
7in
8{
9 options = {
10 services.distccd = {
11 enable = mkEnableOption "distccd, a distributed C/C++ compiler";
12
13 allowedClients = mkOption {
14 type = types.listOf types.str;
15 default = [ "127.0.0.1" ];
16 example = [ "127.0.0.1" "192.168.0.0/24" "10.0.0.0/24" ];
17 description = ''
18 Client IPs which are allowed to connect to distccd in CIDR notation.
19
20 Anyone who can connect to the distccd server can run arbitrary
21 commands on that system as the distcc user, therefore you should use
22 this judiciously.
23 '';
24 };
25
26 jobTimeout = mkOption {
27 type = types.nullOr types.int;
28 default = null;
29 description = ''
30 Maximum duration, in seconds, of a single compilation request.
31 '';
32 };
33
34 logLevel = mkOption {
35 type = types.nullOr (types.enum [ "critical" "error" "warning" "notice" "info" "debug" ]);
36 default = "warning";
37 description = ''
38 Set the minimum severity of error that will be included in the log
39 file. Useful if you only want to see error messages rather than an
40 entry for each connection.
41 '';
42 };
43
44 maxJobs = mkOption {
45 type = types.nullOr types.int;
46 default = null;
47 description = ''
48 Maximum number of tasks distccd should execute at any time.
49 '';
50 };
51
52
53 nice = mkOption {
54 type = types.nullOr types.int;
55 default = null;
56 description = ''
57 Niceness of the compilation tasks.
58 '';
59 };
60
61 openFirewall = mkOption {
62 type = types.bool;
63 default = false;
64 description = ''
65 Opens the specified TCP port for distcc.
66 '';
67 };
68
69 package = mkPackageOption pkgs "distcc" { };
70
71 port = mkOption {
72 type = types.port;
73 default = 3632;
74 description = ''
75 The TCP port which distccd will listen on.
76 '';
77 };
78
79 stats = {
80 enable = mkEnableOption "statistics reporting via HTTP server";
81 port = mkOption {
82 type = types.port;
83 default = 3633;
84 description = ''
85 The TCP port which the distccd statistics HTTP server will listen
86 on.
87 '';
88 };
89 };
90
91 zeroconf = mkOption {
92 type = types.bool;
93 default = false;
94 description = ''
95 Whether to register via mDNS/DNS-SD
96 '';
97 };
98 };
99 };
100
101 config = mkIf cfg.enable {
102 networking.firewall = mkIf cfg.openFirewall {
103 allowedTCPPorts = [ cfg.port ]
104 ++ optionals cfg.stats.enable [ cfg.stats.port ];
105 };
106
107 systemd.services.distccd = {
108 after = [ "network.target" ];
109 wantedBy = [ "multi-user.target" ];
110
111 description = "Distributed C, C++ and Objective-C compiler";
112 documentation = [ "man:distccd(1)" ];
113
114 serviceConfig = {
115 User = "distcc";
116 Group = "distcc";
117 # FIXME: I'd love to get rid of `--enable-tcp-insecure` here, but I'm
118 # not sure how I'm supposed to get distccd to "accept" running a binary
119 # (the compiler) that's outside of /usr/lib.
120 ExecStart = pkgs.writeShellScript "start-distccd" ''
121 export PATH="${pkgs.distccMasquerade}/bin"
122 ${cfg.package}/bin/distccd \
123 --no-detach \
124 --daemon \
125 --enable-tcp-insecure \
126 --port ${toString cfg.port} \
127 ${optionalString (cfg.jobTimeout != null) "--job-lifetime ${toString cfg.jobTimeout}"} \
128 ${optionalString (cfg.logLevel != null) "--log-level ${cfg.logLevel}"} \
129 ${optionalString (cfg.maxJobs != null) "--jobs ${toString cfg.maxJobs}"} \
130 ${optionalString (cfg.nice != null) "--nice ${toString cfg.nice}"} \
131 ${optionalString cfg.stats.enable "--stats"} \
132 ${optionalString cfg.stats.enable "--stats-port ${toString cfg.stats.port}"} \
133 ${optionalString cfg.zeroconf "--zeroconf"} \
134 ${concatMapStrings (c: "--allow ${c} ") cfg.allowedClients}
135 '';
136 };
137 };
138
139 users = {
140 groups.distcc.gid = config.ids.gids.distcc;
141 users.distcc = {
142 description = "distccd user";
143 group = "distcc";
144 uid = config.ids.uids.distcc;
145 };
146 };
147 };
148}