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 listenAddress = mkOption { 52 default = "0.0.0.0"; 53 example = "localhost"; 54 type = 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 }; 60 61 port = mkOption { 62 default = 8080; 63 type = types.int; 64 description = '' 65 Specifies port number on which the jenkins HTTP interface listens. 66 The default is 8080. 67 ''; 68 }; 69 70 prefix = mkOption { 71 default = ""; 72 example = "/jenkins"; 73 type = 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 }; 80 81 packages = mkOption { 82 default = [ pkgs.stdenv pkgs.git pkgs.jdk config.programs.ssh.package pkgs.nix ]; 83 defaultText = "[ pkgs.stdenv pkgs.git pkgs.jdk config.programs.ssh.package pkgs.nix ]"; 84 type = types.listOf types.package; 85 description = '' 86 Packages to add to PATH for the jenkins process. 87 ''; 88 }; 89 90 environment = mkOption { 91 default = { }; 92 type = with types; attrsOf str; 93 description = '' 94 Additional environment variables to be passed to the jenkins process. 95 As a base environment, jenkins receives NIX_PATH from 96 <option>environment.sessionVariables</option>, NIX_REMOTE is set to 97 "daemon" and JENKINS_HOME is set to the value of 98 <option>services.jenkins.home</option>. 99 This option has precedence and can be used to override those 100 mentioned variables. 101 ''; 102 }; 103 104 extraOptions = mkOption { 105 type = types.listOf types.str; 106 default = [ ]; 107 example = [ "--debug=9" ]; 108 description = '' 109 Additional command line arguments to pass to Jenkins. 110 ''; 111 }; 112 }; 113 }; 114 115 config = mkIf cfg.enable { 116 users.extraGroups = optional (cfg.group == "jenkins") { 117 name = "jenkins"; 118 gid = config.ids.gids.jenkins; 119 }; 120 121 users.extraUsers = optional (cfg.user == "jenkins") { 122 name = "jenkins"; 123 description = "jenkins user"; 124 createHome = true; 125 home = cfg.home; 126 group = cfg.group; 127 extraGroups = cfg.extraGroups; 128 useDefaultShell = true; 129 uid = config.ids.uids.jenkins; 130 }; 131 132 systemd.services.jenkins = { 133 description = "Jenkins Continuous Integration Server"; 134 after = [ "network.target" ]; 135 wantedBy = [ "multi-user.target" ]; 136 137 environment = 138 let 139 selectedSessionVars = 140 lib.filterAttrs (n: v: builtins.elem n [ "NIX_PATH" ]) 141 config.environment.sessionVariables; 142 in 143 selectedSessionVars // 144 { JENKINS_HOME = cfg.home; 145 NIX_REMOTE = "daemon"; 146 } // 147 cfg.environment; 148 149 path = cfg.packages; 150 151 # Force .war (re)extraction, or else we might run stale Jenkins. 152 preStart = '' 153 rm -rf ${cfg.home}/war 154 ''; 155 156 script = '' 157 ${pkgs.jdk}/bin/java -jar ${pkgs.jenkins}/webapps/jenkins.war --httpListenAddress=${cfg.listenAddress} \ 158 --httpPort=${toString cfg.port} \ 159 --prefix=${cfg.prefix} \ 160 ${concatStringsSep " " cfg.extraOptions} 161 ''; 162 163 postStart = '' 164 until [[ $(${pkgs.curl.bin}/bin/curl -s --head -w '\n%{http_code}' http://${cfg.listenAddress}:${toString cfg.port}${cfg.prefix} | tail -n1) =~ ^(200|403)$ ]]; do 165 sleep 1 166 done 167 ''; 168 169 serviceConfig = { 170 User = cfg.user; 171 }; 172 }; 173 }; 174}