at 25.11-pre 5.5 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 forEachInstance = 12 f: 13 flip mapAttrs' config.services.fcgiwrap.instances ( 14 name: cfg: nameValuePair "fcgiwrap-${name}" (f cfg) 15 ); 16 17in 18{ 19 imports = 20 forEach 21 [ 22 "enable" 23 "user" 24 "group" 25 "socketType" 26 "socketAddress" 27 "preforkProcesses" 28 ] 29 ( 30 attr: 31 mkRemovedOptionModule [ "services" "fcgiwrap" attr ] '' 32 The global shared fcgiwrap instance is no longer supported due to 33 security issues. 34 Isolated instances should instead be configured through 35 `services.fcgiwrap.instances.*'. 36 '' 37 ); 38 39 options.services.fcgiwrap.instances = mkOption { 40 description = "Configuration for fcgiwrap instances."; 41 default = { }; 42 type = types.attrsOf ( 43 types.submodule ( 44 { config, ... }: 45 { 46 options = { 47 process.prefork = mkOption { 48 type = types.ints.positive; 49 default = 1; 50 description = "Number of processes to prefork."; 51 }; 52 53 process.user = mkOption { 54 type = types.nullOr types.str; 55 default = null; 56 description = '' 57 User as which this instance of fcgiwrap will be run. 58 Set to `null` (the default) to use a dynamically allocated user. 59 ''; 60 }; 61 62 process.group = mkOption { 63 type = types.nullOr types.str; 64 default = null; 65 description = "Group as which this instance of fcgiwrap will be run."; 66 }; 67 68 socket.type = mkOption { 69 type = types.enum [ 70 "unix" 71 "tcp" 72 "tcp6" 73 ]; 74 default = "unix"; 75 description = "Socket type: 'unix', 'tcp' or 'tcp6'."; 76 }; 77 78 socket.address = mkOption { 79 type = types.str; 80 default = "/run/fcgiwrap-${config._module.args.name}.sock"; 81 example = "1.2.3.4:5678"; 82 description = '' 83 Socket address. 84 In case of a UNIX socket, this should be its filesystem path. 85 ''; 86 }; 87 88 socket.user = mkOption { 89 type = types.nullOr types.str; 90 default = null; 91 description = '' 92 User to be set as owner of the UNIX socket. 93 ''; 94 }; 95 96 socket.group = mkOption { 97 type = types.nullOr types.str; 98 default = null; 99 description = '' 100 Group to be set as owner of the UNIX socket. 101 ''; 102 }; 103 104 socket.mode = mkOption { 105 type = types.nullOr types.str; 106 default = if config.socket.type == "unix" then "0600" else null; 107 defaultText = literalExpression '' 108 if config.socket.type == "unix" then "0600" else null 109 ''; 110 description = '' 111 Mode to be set on the UNIX socket. 112 Defaults to private to the socket's owner. 113 ''; 114 }; 115 }; 116 } 117 ) 118 ); 119 }; 120 121 config = { 122 assertions = concatLists ( 123 mapAttrsToList (name: cfg: [ 124 { 125 assertion = cfg.socket.type == "unix" -> cfg.socket.user != null; 126 message = "Socket owner is required for the UNIX socket type."; 127 } 128 { 129 assertion = cfg.socket.type == "unix" -> cfg.socket.group != null; 130 message = "Socket owner is required for the UNIX socket type."; 131 } 132 { 133 assertion = cfg.socket.user != null -> cfg.socket.type == "unix"; 134 message = "Socket owner can only be set for the UNIX socket type."; 135 } 136 { 137 assertion = cfg.socket.group != null -> cfg.socket.type == "unix"; 138 message = "Socket owner can only be set for the UNIX socket type."; 139 } 140 { 141 assertion = cfg.socket.mode != null -> cfg.socket.type == "unix"; 142 message = "Socket mode can only be set for the UNIX socket type."; 143 } 144 ]) config.services.fcgiwrap.instances 145 ); 146 147 systemd.services = forEachInstance (cfg: { 148 after = [ "nss-user-lookup.target" ]; 149 wantedBy = optional (cfg.socket.type != "unix") "multi-user.target"; 150 151 serviceConfig = 152 { 153 ExecStart = '' 154 ${pkgs.fcgiwrap}/sbin/fcgiwrap ${ 155 cli.toGNUCommandLineShell { } ( 156 { 157 c = cfg.process.prefork; 158 } 159 // (optionalAttrs (cfg.socket.type != "unix") { 160 s = "${cfg.socket.type}:${cfg.socket.address}"; 161 }) 162 ) 163 } 164 ''; 165 } 166 // ( 167 if cfg.process.user != null then 168 { 169 User = cfg.process.user; 170 Group = cfg.process.group; 171 } 172 else 173 { 174 DynamicUser = true; 175 } 176 ); 177 }); 178 179 systemd.sockets = forEachInstance ( 180 cfg: 181 mkIf (cfg.socket.type == "unix") { 182 wantedBy = [ "sockets.target" ]; 183 socketConfig = { 184 ListenStream = cfg.socket.address; 185 SocketUser = cfg.socket.user; 186 SocketGroup = cfg.socket.group; 187 SocketMode = cfg.socket.mode; 188 }; 189 } 190 ); 191 }; 192}