1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.jira;
8
9 pkg = cfg.package.override (optionalAttrs cfg.sso.enable {
10 enableSSO = cfg.sso.enable;
11 });
12
13 crowdProperties = pkgs.writeText "crowd.properties" ''
14 application.name ${cfg.sso.applicationName}
15 application.password @NIXOS_JIRA_CROWD_SSO_PWD@
16 application.login.url ${cfg.sso.crowd}/console/
17
18 crowd.server.url ${cfg.sso.crowd}/services/
19 crowd.base.url ${cfg.sso.crowd}/
20
21 session.isauthenticated session.isauthenticated
22 session.tokenkey session.tokenkey
23 session.validationinterval ${toString cfg.sso.validationInterval}
24 session.lastvalidation session.lastvalidation
25 '';
26
27in
28
29{
30 options = {
31 services.jira = {
32 enable = mkEnableOption "Atlassian JIRA service";
33
34 user = mkOption {
35 type = types.str;
36 default = "jira";
37 description = "User which runs JIRA.";
38 };
39
40 group = mkOption {
41 type = types.str;
42 default = "jira";
43 description = "Group which runs JIRA.";
44 };
45
46 home = mkOption {
47 type = types.str;
48 default = "/var/lib/jira";
49 description = "Home directory of the JIRA instance.";
50 };
51
52 listenAddress = mkOption {
53 type = types.str;
54 default = "127.0.0.1";
55 description = "Address to listen on.";
56 };
57
58 listenPort = mkOption {
59 type = types.port;
60 default = 8091;
61 description = "Port to listen on.";
62 };
63
64 catalinaOptions = mkOption {
65 type = types.listOf types.str;
66 default = [];
67 example = [ "-Xms1024m" "-Xmx2048m" ];
68 description = "Java options to pass to catalina/tomcat.";
69 };
70
71 proxy = {
72 enable = mkEnableOption "reverse proxy support";
73
74 name = mkOption {
75 type = types.str;
76 example = "jira.example.com";
77 description = "Virtual hostname at the proxy";
78 };
79
80 port = mkOption {
81 type = types.port;
82 default = 443;
83 example = 80;
84 description = "Port used at the proxy";
85 };
86
87 scheme = mkOption {
88 type = types.str;
89 default = "https";
90 example = "http";
91 description = "Protocol used at the proxy.";
92 };
93
94 secure = mkOption {
95 type = types.bool;
96 default = true;
97 description = "Whether the connections to the proxy should be considered secure.";
98 };
99 };
100
101 sso = {
102 enable = mkEnableOption "SSO with Atlassian Crowd";
103
104 crowd = mkOption {
105 type = types.str;
106 example = "http://localhost:8095/crowd";
107 description = "Crowd Base URL without trailing slash";
108 };
109
110 applicationName = mkOption {
111 type = types.str;
112 example = "jira";
113 description = "Exact name of this JIRA instance in Crowd";
114 };
115
116 applicationPasswordFile = mkOption {
117 type = types.str;
118 description = "Path to the file containing the application password of this JIRA instance in Crowd";
119 };
120
121 validationInterval = mkOption {
122 type = types.int;
123 default = 2;
124 example = 0;
125 description = ''
126 Set to 0, if you want authentication checks to occur on each
127 request. Otherwise set to the number of minutes between request
128 to validate if the user is logged in or out of the Crowd SSO
129 server. Setting this value to 1 or higher will increase the
130 performance of Crowd's integration.
131 '';
132 };
133 };
134
135 package = mkPackageOption pkgs "atlassian-jira" { };
136
137 jrePackage = mkPackageOption pkgs "oraclejre8" {
138 extraDescription = ''
139 ::: {.note }
140 Atlassian only supports the Oracle JRE (JRASERVER-46152).
141 :::
142 '';
143 };
144 };
145 };
146
147 config = mkIf cfg.enable {
148 users.users.${cfg.user} = {
149 isSystemUser = true;
150 group = cfg.group;
151 home = cfg.home;
152 };
153
154 users.groups.${cfg.group} = {};
155
156 systemd.tmpfiles.rules = [
157 "d '${cfg.home}' - ${cfg.user} - - -"
158 "d /run/atlassian-jira - - - - -"
159
160 "L+ /run/atlassian-jira/home - - - - ${cfg.home}"
161 "L+ /run/atlassian-jira/logs - - - - ${cfg.home}/logs"
162 "L+ /run/atlassian-jira/work - - - - ${cfg.home}/work"
163 "L+ /run/atlassian-jira/temp - - - - ${cfg.home}/temp"
164 "L+ /run/atlassian-jira/server.xml - - - - ${cfg.home}/server.xml"
165 ];
166
167 systemd.services.atlassian-jira = {
168 description = "Atlassian JIRA";
169
170 wantedBy = [ "multi-user.target" ];
171 requires = [ "postgresql.service" ];
172 after = [ "postgresql.service" ];
173
174 path = [ cfg.jrePackage pkgs.bash ];
175
176 environment = {
177 JIRA_USER = cfg.user;
178 JIRA_HOME = cfg.home;
179 JAVA_HOME = "${cfg.jrePackage}";
180 CATALINA_OPTS = concatStringsSep " " cfg.catalinaOptions;
181 JAVA_OPTS = mkIf cfg.sso.enable "-Dcrowd.properties=${cfg.home}/crowd.properties";
182 };
183
184 preStart = ''
185 mkdir -p ${cfg.home}/{logs,work,temp,deploy}
186
187 sed -e 's,port="8080",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
188 '' + (lib.optionalString cfg.proxy.enable ''
189 -e 's,protocol="HTTP/1.1",protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${toString cfg.proxy.secure}",' \
190 '') + ''
191 ${pkg}/conf/server.xml.dist > ${cfg.home}/server.xml
192
193 ${optionalString cfg.sso.enable ''
194 install -m660 ${crowdProperties} ${cfg.home}/crowd.properties
195 ${pkgs.replace-secret}/bin/replace-secret \
196 '@NIXOS_JIRA_CROWD_SSO_PWD@' \
197 ${cfg.sso.applicationPasswordFile} \
198 ${cfg.home}/crowd.properties
199 ''}
200 '';
201
202 serviceConfig = {
203 User = cfg.user;
204 Group = cfg.group;
205 PrivateTmp = true;
206 Restart = "on-failure";
207 RestartSec = "10";
208 ExecStart = "${pkg}/bin/start-jira.sh -fg";
209 ExecStop = "${pkg}/bin/stop-jira.sh";
210 };
211 };
212 };
213
214 imports = [
215 (mkRemovedOptionModule [ "services" "jira" "sso" "applicationPassword" ] ''
216 Use `applicationPasswordFile` instead!
217 '')
218 ];
219}