at 25.11-pre 7.2 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9let 10 cfg = config.services.gerrit; 11 12 # NixOS option type for git-like configs 13 gitIniType = 14 with types; 15 let 16 primitiveType = either str (either bool int); 17 multipleType = either primitiveType (listOf primitiveType); 18 sectionType = lazyAttrsOf multipleType; 19 supersectionType = lazyAttrsOf (either multipleType sectionType); 20 in 21 lazyAttrsOf supersectionType; 22 23 gerritConfig = pkgs.writeText "gerrit.conf" (lib.generators.toGitINI cfg.settings); 24 25 replicationConfig = pkgs.writeText "replication.conf" ( 26 lib.generators.toGitINI cfg.replicationSettings 27 ); 28 29 # Wrap the gerrit java with all the java options so it can be called 30 # like a normal CLI app 31 gerrit-cli = pkgs.writeShellScriptBin "gerrit" '' 32 set -euo pipefail 33 jvmOpts=( 34 ${lib.escapeShellArgs cfg.jvmOpts} 35 -Xmx${cfg.jvmHeapLimit} 36 ) 37 exec ${cfg.jvmPackage}/bin/java \ 38 "''${jvmOpts[@]}" \ 39 -jar ${cfg.package}/webapps/${cfg.package.name}.war \ 40 "$@" 41 ''; 42 43 gerrit-plugins = 44 pkgs.runCommand "gerrit-plugins" 45 { 46 buildInputs = [ gerrit-cli ]; 47 } 48 '' 49 shopt -s nullglob 50 mkdir $out 51 52 for name in ${toString cfg.builtinPlugins}; do 53 echo "Installing builtin plugin $name.jar" 54 gerrit cat plugins/$name.jar > $out/$name.jar 55 done 56 57 for file in ${toString cfg.plugins}; do 58 name=$(echo "$file" | cut -d - -f 2-) 59 echo "Installing plugin $name" 60 ln -sf "$file" $out/$name 61 done 62 ''; 63in 64{ 65 options = { 66 services.gerrit = { 67 enable = mkEnableOption "Gerrit service"; 68 69 package = mkPackageOption pkgs "gerrit" { }; 70 71 jvmPackage = mkPackageOption pkgs "jre_headless" { }; 72 73 jvmOpts = mkOption { 74 type = types.listOf types.str; 75 default = [ 76 "-Dflogger.backend_factory=com.google.common.flogger.backend.log4j.Log4jBackendFactory#getInstance" 77 "-Dflogger.logging_context=com.google.gerrit.server.logging.LoggingContext#getInstance" 78 ]; 79 description = "A list of JVM options to start gerrit with."; 80 }; 81 82 jvmHeapLimit = mkOption { 83 type = types.str; 84 default = "1024m"; 85 description = '' 86 How much memory to allocate to the JVM heap 87 ''; 88 }; 89 90 listenAddress = mkOption { 91 type = types.str; 92 default = "[::]:8080"; 93 description = '' 94 `hostname:port` to listen for HTTP traffic. 95 96 This is bound using the systemd socket activation. 97 ''; 98 }; 99 100 settings = mkOption { 101 type = gitIniType; 102 default = { }; 103 description = '' 104 Gerrit configuration. This will be generated to the 105 `etc/gerrit.config` file. 106 ''; 107 }; 108 109 replicationSettings = mkOption { 110 type = gitIniType; 111 default = { }; 112 description = '' 113 Replication configuration. This will be generated to the 114 `etc/replication.config` file. 115 ''; 116 }; 117 118 plugins = mkOption { 119 type = types.listOf types.package; 120 default = [ ]; 121 description = '' 122 List of plugins to add to Gerrit. Each derivation is a jar file 123 itself where the name of the derivation is the name of plugin. 124 ''; 125 }; 126 127 builtinPlugins = mkOption { 128 type = types.listOf (types.enum cfg.package.passthru.plugins); 129 default = [ ]; 130 description = '' 131 List of builtins plugins to install. Those are shipped in the 132 `gerrit.war` file. 133 ''; 134 }; 135 136 serverId = mkOption { 137 type = types.str; 138 description = '' 139 Set a UUID that uniquely identifies the server. 140 141 This can be generated with 142 `nix-shell -p util-linux --run uuidgen`. 143 ''; 144 }; 145 }; 146 }; 147 148 config = mkIf cfg.enable { 149 150 assertions = [ 151 { 152 assertion = cfg.replicationSettings != { } -> elem "replication" cfg.builtinPlugins; 153 message = "Gerrit replicationSettings require enabling the replication plugin"; 154 } 155 ]; 156 157 services.gerrit.settings = { 158 cache.directory = "/var/cache/gerrit"; 159 container.heapLimit = cfg.jvmHeapLimit; 160 gerrit.basePath = lib.mkDefault "git"; 161 gerrit.serverId = cfg.serverId; 162 httpd.inheritChannel = "true"; 163 httpd.listenUrl = lib.mkDefault "http://${cfg.listenAddress}"; 164 index.type = lib.mkDefault "lucene"; 165 }; 166 167 # Add the gerrit CLI to the system to run `gerrit init` and friends. 168 environment.systemPackages = [ gerrit-cli ]; 169 170 systemd.sockets.gerrit = { 171 unitConfig.Description = "Gerrit HTTP socket"; 172 wantedBy = [ "sockets.target" ]; 173 listenStreams = [ cfg.listenAddress ]; 174 }; 175 176 systemd.services.gerrit = { 177 description = "Gerrit"; 178 179 wantedBy = [ "multi-user.target" ]; 180 requires = [ "gerrit.socket" ]; 181 after = [ 182 "gerrit.socket" 183 "network.target" 184 ]; 185 186 path = [ 187 gerrit-cli 188 pkgs.bash 189 pkgs.coreutils 190 pkgs.git 191 pkgs.openssh 192 ]; 193 194 environment = { 195 GERRIT_HOME = "%S/gerrit"; 196 GERRIT_TMP = "%T"; 197 HOME = "%S/gerrit"; 198 XDG_CONFIG_HOME = "%S/gerrit/.config"; 199 }; 200 201 preStart = '' 202 set -euo pipefail 203 204 # bootstrap if nothing exists 205 if [[ ! -d git ]]; then 206 gerrit init --batch --no-auto-start 207 fi 208 209 # install gerrit.war for the plugin manager 210 rm -rf bin 211 mkdir bin 212 ln -sfv ${cfg.package}/webapps/${cfg.package.name}.war bin/gerrit.war 213 214 # copy the config, keep it mutable because Gerrit 215 ln -sfv ${gerritConfig} etc/gerrit.config 216 ln -sfv ${replicationConfig} etc/replication.config 217 218 # install the plugins 219 rm -rf plugins 220 ln -sv ${gerrit-plugins} plugins 221 ''; 222 223 serviceConfig = { 224 CacheDirectory = "gerrit"; 225 DynamicUser = true; 226 ExecStart = "${gerrit-cli}/bin/gerrit daemon --console-log"; 227 LimitNOFILE = 4096; 228 StandardInput = "socket"; 229 StandardOutput = "journal"; 230 StateDirectory = "gerrit"; 231 WorkingDirectory = "%S/gerrit"; 232 AmbientCapabilities = ""; 233 CapabilityBoundingSet = ""; 234 LockPersonality = true; 235 NoNewPrivileges = true; 236 PrivateDevices = true; 237 PrivateTmp = true; 238 ProtectClock = true; 239 ProtectControlGroups = true; 240 ProtectHome = true; 241 ProtectHostname = true; 242 ProtectKernelLogs = true; 243 ProtectKernelModules = true; 244 ProtectKernelTunables = true; 245 ProtectProc = "noaccess"; 246 ProtectSystem = "full"; 247 RestrictAddressFamilies = [ 248 "AF_UNIX" 249 "AF_INET" 250 "AF_INET6" 251 ]; 252 RestrictNamespaces = true; 253 RestrictRealtime = true; 254 RestrictSUIDSGID = true; 255 SystemCallArchitectures = "native"; 256 UMask = 27; 257 }; 258 }; 259 }; 260 261 meta.maintainers = with lib.maintainers; [ 262 edef 263 zimbatm 264 ]; 265 # uses attributes of the linked package 266 meta.buildDocsInSandbox = false; 267}