1{ config, lib, pkgs, ... }:
2with lib;
3let
4 cfg = config.services.jenkins;
5in {
6 options = {
7 services.jenkins = {
8 enable = mkOption {
9 type = types.bool;
10 default = false;
11 description = ''
12 Whether to enable the jenkins continuous integration server.
13 '';
14 };
15
16 user = mkOption {
17 default = "jenkins";
18 type = types.str;
19 description = ''
20 User the jenkins server should execute under.
21 '';
22 };
23
24 group = mkOption {
25 default = "jenkins";
26 type = types.str;
27 description = ''
28 If the default user "jenkins" is configured then this is the primary
29 group of that user.
30 '';
31 };
32
33 extraGroups = mkOption {
34 type = types.listOf 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 };
41
42 home = mkOption {
43 default = "/var/lib/jenkins";
44 type = 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 };
50
51 port = mkOption {
52 default = 8080;
53 type = types.int;
54 description = ''
55 Specifies port number on which the jenkins HTTP interface listens. The default is 8080.
56 '';
57 };
58
59 packages = mkOption {
60 default = [ pkgs.stdenv pkgs.git pkgs.jdk config.programs.ssh.package pkgs.nix ];
61 type = types.listOf types.package;
62 description = ''
63 Packages to add to PATH for the jenkins process.
64 '';
65 };
66
67 environment = mkOption {
68 default = { };
69 type = with types; attrsOf str;
70 description = ''
71 Additional environment variables to be passed to the jenkins process.
72 As a base environment, jenkins receives NIX_PATH, SSL_CERT_FILE and
73 GIT_SSL_CAINFO from <option>environment.sessionVariables</option>,
74 NIX_REMOTE is set to "daemon" and JENKINS_HOME is set to
75 the value of <option>services.jenkins.home</option>. This option has
76 precedence and can be used to override those mentioned variables.
77 '';
78 };
79
80 extraOptions = mkOption {
81 type = types.listOf types.str;
82 default = [ ];
83 example = [ "--debug=9" "--httpListenAddress=localhost" ];
84 description = ''
85 Additional command line arguments to pass to Jenkins.
86 '';
87 };
88 };
89 };
90
91 config = mkIf cfg.enable {
92 users.extraGroups = optional (cfg.group == "jenkins") {
93 name = "jenkins";
94 gid = config.ids.gids.jenkins;
95 };
96
97 users.extraUsers = optional (cfg.user == "jenkins") {
98 name = "jenkins";
99 description = "jenkins user";
100 createHome = true;
101 home = cfg.home;
102 group = cfg.group;
103 extraGroups = cfg.extraGroups;
104 useDefaultShell = true;
105 uid = config.ids.uids.jenkins;
106 };
107
108 systemd.services.jenkins = {
109 description = "Jenkins Continuous Integration Server";
110 after = [ "network.target" ];
111 wantedBy = [ "multi-user.target" ];
112
113 environment =
114 let
115 selectedSessionVars =
116 lib.filterAttrs (n: v: builtins.elem n
117 [ "NIX_PATH"
118 "SSL_CERT_FILE"
119 "GIT_SSL_CAINFO"
120 ])
121 config.environment.sessionVariables;
122 in
123 selectedSessionVars //
124 { JENKINS_HOME = cfg.home;
125 NIX_REMOTE = "daemon";
126 } //
127 cfg.environment;
128
129 path = cfg.packages;
130
131 script = ''
132 ${pkgs.jdk}/bin/java -jar ${pkgs.jenkins} --httpPort=${toString cfg.port} ${concatStringsSep " " cfg.extraOptions}
133 '';
134
135 postStart = ''
136 until ${pkgs.curl}/bin/curl -s -L localhost:${toString cfg.port} ; do
137 sleep 10
138 done
139 while true ; do
140 index=`${pkgs.curl}/bin/curl -s -L localhost:${toString cfg.port}`
141 if [[ !("$index" =~ 'Please wait while Jenkins is restarting' ||
142 "$index" =~ 'Please wait while Jenkins is getting ready to work') ]]; then
143 exit 0
144 fi
145 sleep 30
146 done
147 '';
148
149 serviceConfig = {
150 User = cfg.user;
151 };
152 };
153 };
154}