at 23.11-pre 8.1 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.zope2; 8 9 zope2Opts = { name, ... }: { 10 options = { 11 12 name = mkOption { 13 default = "${name}"; 14 type = types.str; 15 description = lib.mdDoc "The name of the zope2 instance. If undefined, the name of the attribute set will be used."; 16 }; 17 18 threads = mkOption { 19 default = 2; 20 type = types.int; 21 description = lib.mdDoc "Specify the number of threads that Zope's ZServer web server will use to service requests. "; 22 }; 23 24 http_address = mkOption { 25 default = "localhost:8080"; 26 type = types.str; 27 description = lib.mdDoc "Give a port and address for the HTTP server."; 28 }; 29 30 user = mkOption { 31 default = "zope2"; 32 type = types.str; 33 description = lib.mdDoc "The name of the effective user for the Zope process."; 34 }; 35 36 clientHome = mkOption { 37 default = "/var/lib/zope2/${name}"; 38 type = types.path; 39 description = lib.mdDoc "Home directory of zope2 instance."; 40 }; 41 extra = mkOption { 42 default = 43 '' 44 <zodb_db main> 45 mount-point / 46 cache-size 30000 47 <blobstorage> 48 blob-dir /var/lib/zope2/${name}/blobstorage 49 <filestorage> 50 path /var/lib/zope2/${name}/filestorage/Data.fs 51 </filestorage> 52 </blobstorage> 53 </zodb_db> 54 ''; 55 type = types.lines; 56 description = lib.mdDoc "Extra zope.conf"; 57 }; 58 59 packages = mkOption { 60 type = types.listOf types.package; 61 description = lib.mdDoc "The list of packages you want to make available to the zope2 instance."; 62 }; 63 64 }; 65 }; 66 67in 68 69{ 70 71 ###### interface 72 73 options = { 74 75 services.zope2.instances = mkOption { 76 default = {}; 77 type = with types; attrsOf (submodule zope2Opts); 78 example = literalExpression '' 79 { 80 plone01 = { 81 http_address = "127.0.0.1:8080"; 82 extra = 83 ''' 84 <zodb_db main> 85 mount-point / 86 cache-size 30000 87 <blobstorage> 88 blob-dir /var/lib/zope2/plone01/blobstorage 89 <filestorage> 90 path /var/lib/zope2/plone01/filestorage/Data.fs 91 </filestorage> 92 </blobstorage> 93 </zodb_db> 94 '''; 95 }; 96 } 97 ''; 98 description = lib.mdDoc "zope2 instances to be created automatically by the system."; 99 }; 100 }; 101 102 ###### implementation 103 104 config = mkIf (cfg.instances != {}) { 105 106 users.users.zope2 = { 107 isSystemUser = true; 108 group = "zope2"; 109 }; 110 users.groups.zope2 = {}; 111 112 systemd.services = 113 let 114 115 createZope2Instance = opts: name: 116 let 117 interpreter = pkgs.writeScript "interpreter" 118 '' 119 import sys 120 121 _interactive = True 122 if len(sys.argv) > 1: 123 _options, _args = __import__("getopt").getopt(sys.argv[1:], 'ic:m:') 124 _interactive = False 125 for (_opt, _val) in _options: 126 if _opt == '-i': 127 _interactive = True 128 elif _opt == '-c': 129 exec _val 130 elif _opt == '-m': 131 sys.argv[1:] = _args 132 _args = [] 133 __import__("runpy").run_module( 134 _val, {}, "__main__", alter_sys=True) 135 136 if _args: 137 sys.argv[:] = _args 138 __file__ = _args[0] 139 del _options, _args 140 execfile(__file__) 141 142 if _interactive: 143 del _interactive 144 __import__("code").interact(banner="", local=globals()) 145 ''; 146 env = pkgs.buildEnv { 147 name = "zope2-${name}-env"; 148 paths = [ 149 pkgs.python27 150 pkgs.python27Packages.recursivePthLoader 151 pkgs.python27Packages."plone.recipe.zope2instance" 152 ] ++ attrValues pkgs.python27.modules 153 ++ opts.packages; 154 postBuild = 155 '' 156 echo "#!$out/bin/python" > $out/bin/interpreter 157 cat ${interpreter} >> $out/bin/interpreter 158 ''; 159 }; 160 conf = pkgs.writeText "zope2-${name}-conf" 161 '' 162 %define INSTANCEHOME ${env} 163 instancehome $INSTANCEHOME 164 %define CLIENTHOME ${opts.clientHome}/${opts.name} 165 clienthome $CLIENTHOME 166 167 debug-mode off 168 security-policy-implementation C 169 verbose-security off 170 default-zpublisher-encoding utf-8 171 zserver-threads ${toString opts.threads} 172 effective-user ${opts.user} 173 174 pid-filename ${opts.clientHome}/${opts.name}/pid 175 lock-filename ${opts.clientHome}/${opts.name}/lock 176 python-check-interval 1000 177 enable-product-installation off 178 179 <environment> 180 zope_i18n_compile_mo_files false 181 </environment> 182 183 <eventlog> 184 level INFO 185 <logfile> 186 path /var/log/zope2/${name}.log 187 level INFO 188 </logfile> 189 </eventlog> 190 191 <logger access> 192 level WARN 193 <logfile> 194 path /var/log/zope2/${name}-Z2.log 195 format %(message)s 196 </logfile> 197 </logger> 198 199 <http-server> 200 address ${opts.http_address} 201 </http-server> 202 203 <zodb_db temporary> 204 <temporarystorage> 205 name temporary storage for sessioning 206 </temporarystorage> 207 mount-point /temp_folder 208 container-class Products.TemporaryFolder.TemporaryContainer 209 </zodb_db> 210 211 ${opts.extra} 212 ''; 213 ctlScript = pkgs.writeScript "zope2-${name}-ctl-script" 214 '' 215 #!${env}/bin/python 216 217 import sys 218 import plone.recipe.zope2instance.ctl 219 220 if __name__ == '__main__': 221 sys.exit(plone.recipe.zope2instance.ctl.main( 222 ["-C", "${conf}"] 223 + sys.argv[1:])) 224 ''; 225 226 ctl = pkgs.writeScript "zope2-${name}-ctl" 227 '' 228 #!${pkgs.bash}/bin/bash -e 229 export PYTHONHOME=${env} 230 exec ${ctlScript} "$@" 231 ''; 232 in { 233 #description = "${name} instance"; 234 after = [ "network.target" ]; # with RelStorage also add "postgresql.service" 235 wantedBy = [ "multi-user.target" ]; 236 path = opts.packages; 237 preStart = 238 '' 239 mkdir -p /var/log/zope2/ 240 touch /var/log/zope2/${name}.log 241 touch /var/log/zope2/${name}-Z2.log 242 chown ${opts.user} /var/log/zope2/${name}.log 243 chown ${opts.user} /var/log/zope2/${name}-Z2.log 244 245 mkdir -p ${opts.clientHome}/filestorage ${opts.clientHome}/blobstorage 246 mkdir -p ${opts.clientHome}/${opts.name} 247 chown ${opts.user} ${opts.clientHome} -R 248 249 ${ctl} adduser admin admin 250 ''; 251 252 serviceConfig.Type = "forking"; 253 serviceConfig.ExecStart = "${ctl} start"; 254 serviceConfig.ExecStop = "${ctl} stop"; 255 serviceConfig.ExecReload = "${ctl} restart"; 256 }; 257 258 in listToAttrs (map (name: { name = "zope2-${name}"; value = createZope2Instance (builtins.getAttr name cfg.instances) name; }) (builtins.attrNames cfg.instances)); 259 260 }; 261 262}