1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.confluence;
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 ${if cfg.sso.applicationPassword != null then cfg.sso.applicationPassword else "@NIXOS_CONFLUENCE_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.confluence = {
32 enable = mkEnableOption (lib.mdDoc "Atlassian Confluence service");
33
34 user = mkOption {
35 type = types.str;
36 default = "confluence";
37 description = lib.mdDoc "User which runs confluence.";
38 };
39
40 group = mkOption {
41 type = types.str;
42 default = "confluence";
43 description = lib.mdDoc "Group which runs confluence.";
44 };
45
46 home = mkOption {
47 type = types.str;
48 default = "/var/lib/confluence";
49 description = lib.mdDoc "Home directory of the confluence instance.";
50 };
51
52 listenAddress = mkOption {
53 type = types.str;
54 default = "127.0.0.1";
55 description = lib.mdDoc "Address to listen on.";
56 };
57
58 listenPort = mkOption {
59 type = types.port;
60 default = 8090;
61 description = lib.mdDoc "Port to listen on.";
62 };
63
64 catalinaOptions = mkOption {
65 type = types.listOf types.str;
66 default = [];
67 example = [ "-Xms1024m" "-Xmx2048m" "-Dconfluence.disable.peopledirectory.all=true" ];
68 description = lib.mdDoc "Java options to pass to catalina/tomcat.";
69 };
70
71 proxy = {
72 enable = mkEnableOption (lib.mdDoc "proxy support");
73
74 name = mkOption {
75 type = types.str;
76 example = "confluence.example.com";
77 description = lib.mdDoc "Virtual hostname at the proxy";
78 };
79
80 port = mkOption {
81 type = types.port;
82 default = 443;
83 example = 80;
84 description = lib.mdDoc "Port used at the proxy";
85 };
86
87 scheme = mkOption {
88 type = types.str;
89 default = "https";
90 example = "http";
91 description = lib.mdDoc "Protocol used at the proxy.";
92 };
93 };
94
95 sso = {
96 enable = mkEnableOption (lib.mdDoc "SSO with Atlassian Crowd");
97
98 crowd = mkOption {
99 type = types.str;
100 example = "http://localhost:8095/crowd";
101 description = lib.mdDoc "Crowd Base URL without trailing slash";
102 };
103
104 applicationName = mkOption {
105 type = types.str;
106 example = "jira";
107 description = lib.mdDoc "Exact name of this Confluence instance in Crowd";
108 };
109
110 applicationPassword = mkOption {
111 type = types.nullOr types.str;
112 default = null;
113 description = lib.mdDoc "Application password of this Confluence instance in Crowd";
114 };
115
116 applicationPasswordFile = mkOption {
117 type = types.nullOr types.str;
118 default = null;
119 description = lib.mdDoc "Path to the application password for Crowd of Confluence.";
120 };
121
122 validationInterval = mkOption {
123 type = types.int;
124 default = 2;
125 example = 0;
126 description = lib.mdDoc ''
127 Set to 0, if you want authentication checks to occur on each
128 request. Otherwise set to the number of minutes between request
129 to validate if the user is logged in or out of the Crowd SSO
130 server. Setting this value to 1 or higher will increase the
131 performance of Crowd's integration.
132 '';
133 };
134 };
135
136 package = mkOption {
137 type = types.package;
138 default = pkgs.atlassian-confluence;
139 defaultText = literalExpression "pkgs.atlassian-confluence";
140 description = lib.mdDoc "Atlassian Confluence package to use.";
141 };
142
143 jrePackage = mkOption {
144 type = types.package;
145 default = pkgs.oraclejre8;
146 defaultText = literalExpression "pkgs.oraclejre8";
147 description = lib.mdDoc "Note that Atlassian only support the Oracle JRE (JRASERVER-46152).";
148 };
149 };
150 };
151
152 config = mkIf cfg.enable {
153 users.users.${cfg.user} = {
154 isSystemUser = true;
155 group = cfg.group;
156 };
157
158 assertions = [
159 { assertion = cfg.sso.enable -> ((cfg.sso.applicationPassword == null) != (cfg.sso.applicationPasswordFile));
160 message = "Please set either applicationPassword or applicationPasswordFile";
161 }
162 ];
163
164 warnings = mkIf (cfg.sso.enable && cfg.sso.applicationPassword != null) [
165 "Using `services.confluence.sso.applicationPassword` is deprecated! Use `applicationPasswordFile` instead!"
166 ];
167
168 users.groups.${cfg.group} = {};
169
170 systemd.tmpfiles.rules = [
171 "d '${cfg.home}' - ${cfg.user} - - -"
172 "d /run/confluence - - - - -"
173
174 "L+ /run/confluence/home - - - - ${cfg.home}"
175 "L+ /run/confluence/logs - - - - ${cfg.home}/logs"
176 "L+ /run/confluence/temp - - - - ${cfg.home}/temp"
177 "L+ /run/confluence/work - - - - ${cfg.home}/work"
178 "L+ /run/confluence/server.xml - - - - ${cfg.home}/server.xml"
179 ];
180
181 systemd.services.confluence = {
182 description = "Atlassian Confluence";
183
184 wantedBy = [ "multi-user.target" ];
185 requires = [ "postgresql.service" ];
186 after = [ "postgresql.service" ];
187
188 path = [ cfg.jrePackage pkgs.bash ];
189
190 environment = {
191 CONF_USER = cfg.user;
192 JAVA_HOME = "${cfg.jrePackage}";
193 CATALINA_OPTS = concatStringsSep " " cfg.catalinaOptions;
194 JAVA_OPTS = mkIf cfg.sso.enable "-Dcrowd.properties=${cfg.home}/crowd.properties";
195 };
196
197 preStart = ''
198 mkdir -p ${cfg.home}/{logs,work,temp,deploy}
199
200 sed -e 's,port="8090",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
201 '' + (lib.optionalString cfg.proxy.enable ''
202 -e 's,protocol="org.apache.coyote.http11.Http11NioProtocol",protocol="org.apache.coyote.http11.Http11NioProtocol" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}",' \
203 '') + ''
204 ${pkg}/conf/server.xml.dist > ${cfg.home}/server.xml
205
206 ${optionalString cfg.sso.enable ''
207 install -m660 ${crowdProperties} ${cfg.home}/crowd.properties
208 ${optionalString (cfg.sso.applicationPasswordFile != null) ''
209 ${pkgs.replace-secret}/bin/replace-secret \
210 '@NIXOS_CONFLUENCE_CROWD_SSO_PWD@' \
211 ${cfg.sso.applicationPasswordFile} \
212 ${cfg.home}/crowd.properties
213 ''}
214 ''}
215 '';
216
217 serviceConfig = {
218 User = cfg.user;
219 Group = cfg.group;
220 PrivateTmp = true;
221 Restart = "on-failure";
222 RestartSec = "10";
223 ExecStart = "${pkg}/bin/start-confluence.sh -fg";
224 ExecStop = "${pkg}/bin/stop-confluence.sh";
225 };
226 };
227 };
228}