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