vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / continuous-integration / jenkins / default.nix
blobcba1a07ed7898b97eac02455728b41e0bafedfd3
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.jenkins;
4   jenkinsUrl = "http://${cfg.listenAddress}:${toString cfg.port}${cfg.prefix}";
5 in {
6   options = {
7     services.jenkins = {
8       enable = lib.mkOption {
9         type = lib.types.bool;
10         default = false;
11         description = ''
12           Whether to enable the jenkins continuous integration server.
13         '';
14       };
16       user = lib.mkOption {
17         default = "jenkins";
18         type = lib.types.str;
19         description = ''
20           User the jenkins server should execute under.
21         '';
22       };
24       group = lib.mkOption {
25         default = "jenkins";
26         type = lib.types.str;
27         description = ''
28           If the default user "jenkins" is configured then this is the primary
29           group of that user.
30         '';
31       };
33       extraGroups = lib.mkOption {
34         type = lib.types.listOf lib.types.str;
35         default = [ ];
36         example = [ "wheel" "dialout" ];
37         description = ''
38           List of extra groups that the "jenkins" user should be a part of.
39         '';
40       };
42       home = lib.mkOption {
43         default = "/var/lib/jenkins";
44         type = lib.types.path;
45         description = ''
46           The path to use as JENKINS_HOME. If the default user "jenkins" is configured then
47           this is the home of the "jenkins" user.
48         '';
49       };
51       listenAddress = lib.mkOption {
52         default = "0.0.0.0";
53         example = "localhost";
54         type = lib.types.str;
55         description = ''
56           Specifies the bind address on which the jenkins HTTP interface listens.
57           The default is the wildcard address.
58         '';
59       };
61       port = lib.mkOption {
62         default = 8080;
63         type = lib.types.port;
64         description = ''
65           Specifies port number on which the jenkins HTTP interface listens.
66           The default is 8080.
67         '';
68       };
70       prefix = lib.mkOption {
71         default = "";
72         example = "/jenkins";
73         type = lib.types.str;
74         description = ''
75           Specifies a urlPrefix to use with jenkins.
76           If the example /jenkins is given, the jenkins server will be
77           accessible using localhost:8080/jenkins.
78         '';
79       };
81       package = lib.mkPackageOption pkgs "jenkins" { };
83       packages = lib.mkOption {
84         default = [ pkgs.stdenv pkgs.git pkgs.jdk17 config.programs.ssh.package pkgs.nix ];
85         defaultText = lib.literalExpression "[ pkgs.stdenv pkgs.git pkgs.jdk17 config.programs.ssh.package pkgs.nix ]";
86         type = lib.types.listOf lib.types.package;
87         description = ''
88           Packages to add to PATH for the jenkins process.
89         '';
90       };
92       environment = lib.mkOption {
93         default = { };
94         type = with lib.types; attrsOf str;
95         description = ''
96           Additional environment variables to be passed to the jenkins process.
97           As a base environment, jenkins receives NIX_PATH from
98           {option}`environment.sessionVariables`, NIX_REMOTE is set to
99           "daemon" and JENKINS_HOME is set to the value of
100           {option}`services.jenkins.home`.
101           This option has precedence and can be used to override those
102           mentioned variables.
103         '';
104       };
106       plugins = lib.mkOption {
107         default = null;
108         type = lib.types.nullOr (lib.types.attrsOf lib.types.package);
109         description = ''
110           A set of plugins to activate. Note that this will completely
111           remove and replace any previously installed plugins. If you
112           have manually-installed plugins that you want to keep while
113           using this module, set this option to
114           `null`. You can generate this set with a
115           tool such as `jenkinsPlugins2nix`.
116         '';
117         example = lib.literalExpression ''
118           import path/to/jenkinsPlugins2nix-generated-plugins.nix { inherit (pkgs) fetchurl stdenv; }
119         '';
120       };
122       extraOptions = lib.mkOption {
123         type = lib.types.listOf lib.types.str;
124         default = [ ];
125         example = [ "--debug=9" ];
126         description = ''
127           Additional command line arguments to pass to Jenkins.
128         '';
129       };
131       extraJavaOptions = lib.mkOption {
132         type = lib.types.listOf lib.types.str;
133         default = [ ];
134         example = [ "-Xmx80m" ];
135         description = ''
136           Additional command line arguments to pass to the Java run time (as opposed to Jenkins).
137         '';
138       };
140       withCLI = lib.mkOption {
141         type = lib.types.bool;
142         default = false;
143         description = ''
144           Whether to make the CLI available.
146           More info about the CLI available at
147           [
148           https://www.jenkins.io/doc/book/managing/cli](https://www.jenkins.io/doc/book/managing/cli) .
149         '';
150       };
151     };
152   };
154   config = lib.mkIf cfg.enable {
155     environment = {
156       # server references the dejavu fonts
157       systemPackages = [
158         pkgs.dejavu_fonts
159       ] ++ lib.optional cfg.withCLI cfg.package;
161       variables = {}
162         // lib.optionalAttrs cfg.withCLI {
163           # Make it more convenient to use the `jenkins-cli`.
164           JENKINS_URL = jenkinsUrl;
165         };
166     };
168     users.groups = lib.optionalAttrs (cfg.group == "jenkins") {
169       jenkins.gid = config.ids.gids.jenkins;
170     };
172     users.users = lib.optionalAttrs (cfg.user == "jenkins") {
173       jenkins = {
174         description = "jenkins user";
175         createHome = true;
176         home = cfg.home;
177         group = cfg.group;
178         extraGroups = cfg.extraGroups;
179         useDefaultShell = true;
180         uid = config.ids.uids.jenkins;
181       };
182     };
184     systemd.services.jenkins = {
185       description = "Jenkins Continuous Integration Server";
186       after = [ "network.target" ];
187       wantedBy = [ "multi-user.target" ];
189       environment =
190         let
191           selectedSessionVars =
192             lib.filterAttrs (n: v: builtins.elem n [ "NIX_PATH" ])
193               config.environment.sessionVariables;
194         in
195           selectedSessionVars //
196           { JENKINS_HOME = cfg.home;
197             NIX_REMOTE = "daemon";
198           } //
199           cfg.environment;
201       path = cfg.packages;
203       # Force .war (re)extraction, or else we might run stale Jenkins.
205       preStart =
206         let replacePlugins =
207               lib.optionalString (cfg.plugins != null) (
208                 let pluginCmds = lib.mapAttrsToList
209                       (n: v: "cp ${v} ${cfg.home}/plugins/${n}.jpi")
210                       cfg.plugins;
211                 in ''
212                   rm -r ${cfg.home}/plugins || true
213                   mkdir -p ${cfg.home}/plugins
214                   ${lib.concatStringsSep "\n" pluginCmds}
215                 '');
216         in ''
217           rm -rf ${cfg.home}/war
218           ${replacePlugins}
219         '';
221       # For reference: https://wiki.jenkins.io/display/JENKINS/JenkinsLinuxStartupScript
222       script = ''
223         ${pkgs.jdk17}/bin/java ${lib.concatStringsSep " " cfg.extraJavaOptions} -jar ${cfg.package}/webapps/jenkins.war --httpListenAddress=${cfg.listenAddress} \
224                                                   --httpPort=${toString cfg.port} \
225                                                   --prefix=${cfg.prefix} \
226                                                   -Djava.awt.headless=true \
227                                                   ${lib.concatStringsSep " " cfg.extraOptions}
228       '';
230       postStart = ''
231         until [[ $(${pkgs.curl.bin}/bin/curl -L -s --head -w '\n%{http_code}' ${jenkinsUrl} | tail -n1) =~ ^(200|403)$ ]]; do
232           sleep 1
233         done
234       '';
236       serviceConfig = {
237         User = cfg.user;
238         StateDirectory = lib.mkIf (lib.hasPrefix "/var/lib/jenkins" cfg.home) "jenkins";
239         # For (possible) socket use
240         RuntimeDirectory = "jenkins";
241       };
242     };
243   };