at 17.09-beta 14 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.tomcat; 8 tomcat = cfg.package; 9in 10 11{ 12 13 meta = { 14 maintainers = with maintainers; [ danbst ]; 15 }; 16 17 ###### interface 18 19 options = { 20 21 services.tomcat = { 22 23 enable = mkOption { 24 default = false; 25 description = "Whether to enable Apache Tomcat"; 26 }; 27 28 package = mkOption { 29 type = types.package; 30 default = pkgs.tomcat85; 31 defaultText = "pkgs.tomcat85"; 32 example = lib.literalExample "pkgs.tomcatUnstable"; 33 description = '' 34 Which tomcat package to use. 35 ''; 36 }; 37 38 baseDir = mkOption { 39 default = "/var/tomcat"; 40 description = "Location where Tomcat stores configuration files, webapplications and logfiles"; 41 }; 42 43 extraGroups = mkOption { 44 default = []; 45 example = [ "users" ]; 46 description = "Defines extra groups to which the tomcat user belongs."; 47 }; 48 49 user = mkOption { 50 default = "tomcat"; 51 description = "User account under which Apache Tomcat runs."; 52 }; 53 54 group = mkOption { 55 default = "tomcat"; 56 description = "Group account under which Apache Tomcat runs."; 57 }; 58 59 javaOpts = mkOption { 60 default = ""; 61 description = "Parameters to pass to the Java Virtual Machine which spawns Apache Tomcat"; 62 }; 63 64 catalinaOpts = mkOption { 65 default = ""; 66 description = "Parameters to pass to the Java Virtual Machine which spawns the Catalina servlet container"; 67 }; 68 69 sharedLibs = mkOption { 70 default = []; 71 description = "List containing JAR files or directories with JAR files which are libraries shared by the web applications"; 72 }; 73 74 commonLibs = mkOption { 75 default = []; 76 description = "List containing JAR files or directories with JAR files which are libraries shared by the web applications and the servlet container"; 77 }; 78 79 webapps = mkOption { 80 type = types.listOf types.package; 81 default = [ tomcat.webapps ]; 82 defaultText = "[ tomcat.webapps ]"; 83 description = "List containing WAR files or directories with WAR files which are web applications to be deployed on Tomcat"; 84 }; 85 86 virtualHosts = mkOption { 87 default = []; 88 description = "List consisting of a virtual host name and a list of web applications to deploy on each virtual host"; 89 }; 90 91 logPerVirtualHost = mkOption { 92 default = false; 93 description = "Whether to enable logging per virtual host."; 94 }; 95 96 jdk = mkOption { 97 type = types.package; 98 default = pkgs.jdk; 99 defaultText = "pkgs.jdk"; 100 description = "Which JDK to use."; 101 }; 102 103 axis2 = { 104 105 enable = mkOption { 106 default = false; 107 description = "Whether to enable an Apache Axis2 container"; 108 }; 109 110 services = mkOption { 111 default = []; 112 description = "List containing AAR files or directories with AAR files which are web services to be deployed on Axis2"; 113 }; 114 115 }; 116 117 }; 118 119 }; 120 121 122 ###### implementation 123 124 config = mkIf config.services.tomcat.enable { 125 126 users.extraGroups = singleton 127 { name = "tomcat"; 128 gid = config.ids.gids.tomcat; 129 }; 130 131 users.extraUsers = singleton 132 { name = "tomcat"; 133 uid = config.ids.uids.tomcat; 134 description = "Tomcat user"; 135 home = "/homeless-shelter"; 136 extraGroups = cfg.extraGroups; 137 }; 138 139 systemd.services.tomcat = { 140 description = "Apache Tomcat server"; 141 wantedBy = [ "multi-user.target" ]; 142 after = [ "network.target" ]; 143 serviceConfig.Type = "oneshot"; 144 serviceConfig.RemainAfterExit = true; 145 146 preStart = '' 147 # Create the base directory 148 mkdir -p ${cfg.baseDir} 149 150 # Create a symlink to the bin directory of the tomcat component 151 ln -sfn ${tomcat}/bin ${cfg.baseDir}/bin 152 153 # Create a conf/ directory 154 mkdir -p ${cfg.baseDir}/conf 155 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/conf 156 157 # Symlink the config files in the conf/ directory (except for catalina.properties and server.xml) 158 for i in $(ls ${tomcat}/conf | grep -v catalina.properties | grep -v server.xml) 159 do 160 ln -sfn ${tomcat}/conf/$i ${cfg.baseDir}/conf/`basename $i` 161 done 162 163 # Create subdirectory for virtual hosts 164 mkdir -p ${cfg.baseDir}/virtualhosts 165 166 # Create a modified catalina.properties file 167 # Change all references from CATALINA_HOME to CATALINA_BASE and add support for shared libraries 168 sed -e 's|''${catalina.home}|''${catalina.base}|g' \ 169 -e 's|shared.loader=|shared.loader=''${catalina.base}/shared/lib/*.jar|' \ 170 ${tomcat}/conf/catalina.properties > ${cfg.baseDir}/conf/catalina.properties 171 172 # Create a modified server.xml which also includes all virtual hosts 173 sed -e "/<Engine name=\"Catalina\" defaultHost=\"localhost\">/a\ ${ 174 toString (map (virtualHost: ''<Host name=\"${virtualHost.name}\" appBase=\"virtualhosts/${virtualHost.name}/webapps\" unpackWARs=\"true\" autoDeploy=\"true\" xmlValidation=\"false\" xmlNamespaceAware=\"false\" >${if cfg.logPerVirtualHost then ''<Valve className=\"org.apache.catalina.valves.AccessLogValve\" directory=\"logs/${virtualHost.name}\" prefix=\"${virtualHost.name}_access_log.\" pattern=\"combined\" resolveHosts=\"false\"/>'' else ""}</Host>'') cfg.virtualHosts)}" \ 175 ${tomcat}/conf/server.xml > ${cfg.baseDir}/conf/server.xml 176 177 # Create a logs/ directory 178 mkdir -p ${cfg.baseDir}/logs 179 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/logs 180 ${if cfg.logPerVirtualHost then 181 toString (map (h: '' 182 mkdir -p ${cfg.baseDir}/logs/${h.name} 183 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/logs/${h.name} 184 '') cfg.virtualHosts) else ''''} 185 186 # Create a temp/ directory 187 mkdir -p ${cfg.baseDir}/temp 188 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/temp 189 190 # Create a lib/ directory 191 mkdir -p ${cfg.baseDir}/lib 192 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/lib 193 194 # Create a shared/lib directory 195 mkdir -p ${cfg.baseDir}/shared/lib 196 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/shared/lib 197 198 # Create a webapps/ directory 199 mkdir -p ${cfg.baseDir}/webapps 200 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/webapps 201 202 # Symlink all the given common libs files or paths into the lib/ directory 203 for i in ${tomcat} ${toString cfg.commonLibs} 204 do 205 if [ -f $i ] 206 then 207 # If the given web application is a file, symlink it into the common/lib/ directory 208 ln -sfn $i ${cfg.baseDir}/lib/`basename $i` 209 elif [ -d $i ] 210 then 211 # If the given web application is a directory, then iterate over the files 212 # in the special purpose directories and symlink them into the tomcat tree 213 214 for j in $i/lib/* 215 do 216 ln -sfn $j ${cfg.baseDir}/lib/`basename $j` 217 done 218 fi 219 done 220 221 # Symlink all the given shared libs files or paths into the shared/lib/ directory 222 for i in ${toString cfg.sharedLibs} 223 do 224 if [ -f $i ] 225 then 226 # If the given web application is a file, symlink it into the common/lib/ directory 227 ln -sfn $i ${cfg.baseDir}/shared/lib/`basename $i` 228 elif [ -d $i ] 229 then 230 # If the given web application is a directory, then iterate over the files 231 # in the special purpose directories and symlink them into the tomcat tree 232 233 for j in $i/shared/lib/* 234 do 235 ln -sfn $j ${cfg.baseDir}/shared/lib/`basename $j` 236 done 237 fi 238 done 239 240 # Symlink all the given web applications files or paths into the webapps/ directory 241 for i in ${toString cfg.webapps} 242 do 243 if [ -f $i ] 244 then 245 # If the given web application is a file, symlink it into the webapps/ directory 246 ln -sfn $i ${cfg.baseDir}/webapps/`basename $i` 247 elif [ -d $i ] 248 then 249 # If the given web application is a directory, then iterate over the files 250 # in the special purpose directories and symlink them into the tomcat tree 251 252 for j in $i/webapps/* 253 do 254 ln -sfn $j ${cfg.baseDir}/webapps/`basename $j` 255 done 256 257 # Also symlink the configuration files if they are included 258 if [ -d $i/conf/Catalina ] 259 then 260 for j in $i/conf/Catalina/* 261 do 262 mkdir -p ${cfg.baseDir}/conf/Catalina/localhost 263 ln -sfn $j ${cfg.baseDir}/conf/Catalina/localhost/`basename $j` 264 done 265 fi 266 fi 267 done 268 269 ${toString (map (virtualHost: '' 270 # Create webapps directory for the virtual host 271 mkdir -p ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps 272 273 # Modify ownership 274 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps 275 276 # Symlink all the given web applications files or paths into the webapps/ directory 277 # of this virtual host 278 for i in "${if virtualHost ? webapps then toString virtualHost.webapps else ""}" 279 do 280 if [ -f $i ] 281 then 282 # If the given web application is a file, symlink it into the webapps/ directory 283 ln -sfn $i ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps/`basename $i` 284 elif [ -d $i ] 285 then 286 # If the given web application is a directory, then iterate over the files 287 # in the special purpose directories and symlink them into the tomcat tree 288 289 for j in $i/webapps/* 290 do 291 ln -sfn $j ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps/`basename $j` 292 done 293 294 # Also symlink the configuration files if they are included 295 if [ -d $i/conf/Catalina ] 296 then 297 for j in $i/conf/Catalina/* 298 do 299 mkdir -p ${cfg.baseDir}/conf/Catalina/${virtualHost.name} 300 ln -sfn $j ${cfg.baseDir}/conf/Catalina/${virtualHost.name}/`basename $j` 301 done 302 fi 303 fi 304 done 305 306 '' 307 ) cfg.virtualHosts) } 308 309 # Create a work/ directory 310 mkdir -p ${cfg.baseDir}/work 311 chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/work 312 313 ${if cfg.axis2.enable then 314 '' 315 # Copy the Axis2 web application 316 cp -av ${pkgs.axis2}/webapps/axis2 ${cfg.baseDir}/webapps 317 318 # Turn off addressing, which causes many errors 319 sed -i -e 's%<module ref="addressing"/>%<!-- <module ref="addressing"/> -->%' ${cfg.baseDir}/webapps/axis2/WEB-INF/conf/axis2.xml 320 321 # Modify permissions on the Axis2 application 322 chown -R ${cfg.user}:${cfg.group} ${cfg.baseDir}/webapps/axis2 323 324 # Symlink all the given web service files or paths into the webapps/axis2/WEB-INF/services directory 325 for i in ${toString cfg.axis2.services} 326 do 327 if [ -f $i ] 328 then 329 # If the given web service is a file, symlink it into the webapps/axis2/WEB-INF/services 330 ln -sfn $i ${cfg.baseDir}/webapps/axis2/WEB-INF/services/`basename $i` 331 elif [ -d $i ] 332 then 333 # If the given web application is a directory, then iterate over the files 334 # in the special purpose directories and symlink them into the tomcat tree 335 336 for j in $i/webapps/axis2/WEB-INF/services/* 337 do 338 ln -sfn $j ${cfg.baseDir}/webapps/axis2/WEB-INF/services/`basename $j` 339 done 340 341 # Also symlink the configuration files if they are included 342 if [ -d $i/conf/Catalina ] 343 then 344 for j in $i/conf/Catalina/* 345 do 346 ln -sfn $j ${cfg.baseDir}/conf/Catalina/localhost/`basename $j` 347 done 348 fi 349 fi 350 done 351 '' 352 else ""} 353 ''; 354 355 script = '' 356 ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${tomcat}/bin/startup.sh' 357 ''; 358 359 preStop = '' 360 echo "Stopping tomcat..." 361 CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${tomcat}/bin/shutdown.sh 362 ''; 363 364 }; 365 366 }; 367 368}