at 25.11-pre 15 kB view raw
1{ 2 lib, 3 pkgs, 4 config, 5 options, 6 ... 7}: 8 9let 10 cfg = config.services.nifi; 11 opt = options.services.nifi; 12 13 env = { 14 NIFI_OVERRIDE_NIFIENV = "true"; 15 NIFI_HOME = "/var/lib/nifi"; 16 NIFI_PID_DIR = "/run/nifi"; 17 NIFI_LOG_DIR = "/var/log/nifi"; 18 }; 19 20 envFile = pkgs.writeText "nifi.env" ( 21 lib.concatMapStrings (s: s + "\n") ( 22 (lib.concatLists ( 23 lib.mapAttrsToList (name: value: lib.optional (value != null) ''${name}="${toString value}"'') env 24 )) 25 ) 26 ); 27 28 nifiEnv = pkgs.writeShellScriptBin "nifi-env" '' 29 set -a 30 source "${envFile}" 31 eval -- "\$@" 32 ''; 33 34in 35{ 36 options = { 37 services.nifi = { 38 enable = lib.mkEnableOption "Apache NiFi"; 39 40 package = lib.mkOption { 41 type = lib.types.package; 42 default = pkgs.nifi; 43 defaultText = lib.literalExpression "pkgs.nifi"; 44 description = "Apache NiFi package to use."; 45 }; 46 47 user = lib.mkOption { 48 type = lib.types.str; 49 default = "nifi"; 50 description = "User account where Apache NiFi runs."; 51 }; 52 53 group = lib.mkOption { 54 type = lib.types.str; 55 default = "nifi"; 56 description = "Group account where Apache NiFi runs."; 57 }; 58 59 enableHTTPS = lib.mkOption { 60 type = lib.types.bool; 61 default = true; 62 description = "Enable HTTPS protocol. Don`t use in production."; 63 }; 64 65 listenHost = lib.mkOption { 66 type = lib.types.str; 67 default = if cfg.enableHTTPS then "0.0.0.0" else "127.0.0.1"; 68 defaultText = lib.literalExpression '' 69 if config.${opt.enableHTTPS} 70 then "0.0.0.0" 71 else "127.0.0.1" 72 ''; 73 description = "Bind to an ip for Apache NiFi web-ui."; 74 }; 75 76 listenPort = lib.mkOption { 77 type = lib.types.int; 78 default = if cfg.enableHTTPS then 8443 else 8080; 79 defaultText = lib.literalExpression '' 80 if config.${opt.enableHTTPS} 81 then "8443" 82 else "8000" 83 ''; 84 description = "Bind to a port for Apache NiFi web-ui."; 85 }; 86 87 proxyHost = lib.mkOption { 88 type = lib.types.nullOr lib.types.str; 89 default = if cfg.enableHTTPS then "0.0.0.0" else null; 90 defaultText = lib.literalExpression '' 91 if config.${opt.enableHTTPS} 92 then "0.0.0.0" 93 else null 94 ''; 95 description = "Allow requests from a specific host."; 96 }; 97 98 proxyPort = lib.mkOption { 99 type = lib.types.nullOr lib.types.int; 100 default = if cfg.enableHTTPS then 8443 else null; 101 defaultText = lib.literalExpression '' 102 if config.${opt.enableHTTPS} 103 then "8443" 104 else null 105 ''; 106 description = "Allow requests from a specific port."; 107 }; 108 109 initUser = lib.mkOption { 110 type = lib.types.nullOr lib.types.str; 111 default = null; 112 description = "Initial user account for Apache NiFi. Username must be at least 4 characters."; 113 }; 114 115 initPasswordFile = lib.mkOption { 116 type = lib.types.nullOr lib.types.path; 117 default = null; 118 example = "/run/keys/nifi/password-nifi"; 119 description = "nitial password for Apache NiFi. Password must be at least 12 characters."; 120 }; 121 122 initJavaHeapSize = lib.mkOption { 123 type = lib.types.nullOr lib.types.int; 124 default = null; 125 example = 1024; 126 description = "Set the initial heap size for the JVM in MB."; 127 }; 128 129 maxJavaHeapSize = lib.mkOption { 130 type = lib.types.nullOr lib.types.int; 131 default = null; 132 example = 2048; 133 description = "Set the initial heap size for the JVM in MB."; 134 }; 135 }; 136 }; 137 138 config = lib.mkIf cfg.enable { 139 assertions = [ 140 { 141 assertion = cfg.initUser != null || cfg.initPasswordFile == null; 142 message = '' 143 <option>services.nifi.initUser</option> needs to be set if <option>services.nifi.initPasswordFile</option> enabled. 144 ''; 145 } 146 { 147 assertion = cfg.initUser == null || cfg.initPasswordFile != null; 148 message = '' 149 <option>services.nifi.initPasswordFile</option> needs to be set if <option>services.nifi.initUser</option> enabled. 150 ''; 151 } 152 { 153 assertion = cfg.proxyHost == null || cfg.proxyPort != null; 154 message = '' 155 <option>services.nifi.proxyPort</option> needs to be set if <option>services.nifi.proxyHost</option> value specified. 156 ''; 157 } 158 { 159 assertion = cfg.proxyHost != null || cfg.proxyPort == null; 160 message = '' 161 <option>services.nifi.proxyHost</option> needs to be set if <option>services.nifi.proxyPort</option> value specified. 162 ''; 163 } 164 { 165 assertion = cfg.initJavaHeapSize == null || cfg.maxJavaHeapSize != null; 166 message = '' 167 <option>services.nifi.maxJavaHeapSize</option> needs to be set if <option>services.nifi.initJavaHeapSize</option> value specified. 168 ''; 169 } 170 { 171 assertion = cfg.initJavaHeapSize != null || cfg.maxJavaHeapSize == null; 172 message = '' 173 <option>services.nifi.initJavaHeapSize</option> needs to be set if <option>services.nifi.maxJavaHeapSize</option> value specified. 174 ''; 175 } 176 ]; 177 178 warnings = lib.optional (cfg.enableHTTPS == false) '' 179 Please do not disable HTTPS mode in production. In this mode, access to the nifi is opened without authentication. 180 ''; 181 182 systemd.tmpfiles.settings."10-nifi" = { 183 "/var/lib/nifi/conf".d = { 184 inherit (cfg) user group; 185 mode = "0750"; 186 }; 187 "/var/lib/nifi/lib"."L+" = { 188 argument = "${cfg.package}/lib"; 189 }; 190 }; 191 192 systemd.services.nifi = { 193 description = "Apache NiFi"; 194 after = [ "network.target" ]; 195 wantedBy = [ "multi-user.target" ]; 196 197 environment = env; 198 path = [ pkgs.gawk ]; 199 200 serviceConfig = { 201 Type = "forking"; 202 PIDFile = "/run/nifi/nifi.pid"; 203 ExecStartPre = pkgs.writeScript "nifi-pre-start.sh" '' 204 #!/bin/sh 205 umask 077 206 test -f '/var/lib/nifi/conf/authorizers.xml' || (cp '${cfg.package}/share/nifi/conf/authorizers.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/authorizers.xml') 207 test -f '/var/lib/nifi/conf/bootstrap.conf' || (cp '${cfg.package}/share/nifi/conf/bootstrap.conf' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/bootstrap.conf') 208 test -f '/var/lib/nifi/conf/bootstrap-hashicorp-vault.conf' || (cp '${cfg.package}/share/nifi/conf/bootstrap-hashicorp-vault.conf' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/bootstrap-hashicorp-vault.conf') 209 test -f '/var/lib/nifi/conf/bootstrap-notification-services.xml' || (cp '${cfg.package}/share/nifi/conf/bootstrap-notification-services.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/bootstrap-notification-services.xml') 210 test -f '/var/lib/nifi/conf/logback.xml' || (cp '${cfg.package}/share/nifi/conf/logback.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/logback.xml') 211 test -f '/var/lib/nifi/conf/login-identity-providers.xml' || (cp '${cfg.package}/share/nifi/conf/login-identity-providers.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/login-identity-providers.xml') 212 test -f '/var/lib/nifi/conf/nifi.properties' || (cp '${cfg.package}/share/nifi/conf/nifi.properties' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/nifi.properties') 213 test -f '/var/lib/nifi/conf/stateless-logback.xml' || (cp '${cfg.package}/share/nifi/conf/stateless-logback.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/stateless-logback.xml') 214 test -f '/var/lib/nifi/conf/stateless.properties' || (cp '${cfg.package}/share/nifi/conf/stateless.properties' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/stateless.properties') 215 test -f '/var/lib/nifi/conf/state-management.xml' || (cp '${cfg.package}/share/nifi/conf/state-management.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/state-management.xml') 216 test -f '/var/lib/nifi/conf/zookeeper.properties' || (cp '${cfg.package}/share/nifi/conf/zookeeper.properties' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/zookeeper.properties') 217 test -d '/var/lib/nifi/docs/html' || (mkdir -p /var/lib/nifi/docs && cp -r '${cfg.package}/share/nifi/docs/html' '/var/lib/nifi/docs/html') 218 ${lib.optionalString ((cfg.initUser != null) && (cfg.initPasswordFile != null)) '' 219 awk -F'[<|>]' '/property name="Username"/ {if ($3!="") f=1} END{exit !f}' /var/lib/nifi/conf/login-identity-providers.xml || ${cfg.package}/bin/nifi.sh set-single-user-credentials ${cfg.initUser} $(cat ${cfg.initPasswordFile}) 220 ''} 221 ${lib.optionalString (cfg.enableHTTPS == false) '' 222 sed -i /var/lib/nifi/conf/nifi.properties \ 223 -e 's|nifi.remote.input.secure=.*|nifi.remote.input.secure=false|g' \ 224 -e 's|nifi.web.http.host=.*|nifi.web.http.host=${cfg.listenHost}|g' \ 225 -e 's|nifi.web.http.port=.*|nifi.web.http.port=${(toString cfg.listenPort)}|g' \ 226 -e 's|nifi.web.https.host=.*|nifi.web.https.host=|g' \ 227 -e 's|nifi.web.https.port=.*|nifi.web.https.port=|g' \ 228 -e 's|nifi.security.keystore=.*|nifi.security.keystore=|g' \ 229 -e 's|nifi.security.keystoreType=.*|nifi.security.keystoreType=|g' \ 230 -e 's|nifi.security.truststore=.*|nifi.security.truststore=|g' \ 231 -e 's|nifi.security.truststoreType=.*|nifi.security.truststoreType=|g' \ 232 -e '/nifi.security.keystorePasswd/s|^|#|' \ 233 -e '/nifi.security.keyPasswd/s|^|#|' \ 234 -e '/nifi.security.truststorePasswd/s|^|#|' 235 ''} 236 ${lib.optionalString (cfg.enableHTTPS == true) '' 237 sed -i /var/lib/nifi/conf/nifi.properties \ 238 -e 's|nifi.remote.input.secure=.*|nifi.remote.input.secure=true|g' \ 239 -e 's|nifi.web.http.host=.*|nifi.web.http.host=|g' \ 240 -e 's|nifi.web.http.port=.*|nifi.web.http.port=|g' \ 241 -e 's|nifi.web.https.host=.*|nifi.web.https.host=${cfg.listenHost}|g' \ 242 -e 's|nifi.web.https.port=.*|nifi.web.https.port=${(toString cfg.listenPort)}|g' \ 243 -e 's|nifi.security.keystore=.*|nifi.security.keystore=./conf/keystore.p12|g' \ 244 -e 's|nifi.security.keystoreType=.*|nifi.security.keystoreType=PKCS12|g' \ 245 -e 's|nifi.security.truststore=.*|nifi.security.truststore=./conf/truststore.p12|g' \ 246 -e 's|nifi.security.truststoreType=.*|nifi.security.truststoreType=PKCS12|g' \ 247 -e '/nifi.security.keystorePasswd/s|^#\+||' \ 248 -e '/nifi.security.keyPasswd/s|^#\+||' \ 249 -e '/nifi.security.truststorePasswd/s|^#\+||' 250 ''} 251 ${lib.optionalString 252 ((cfg.enableHTTPS == true) && (cfg.proxyHost != null) && (cfg.proxyPort != null)) 253 '' 254 sed -i /var/lib/nifi/conf/nifi.properties \ 255 -e 's|nifi.web.proxy.host=.*|nifi.web.proxy.host=${cfg.proxyHost}:${(toString cfg.proxyPort)}|g' 256 '' 257 } 258 ${lib.optionalString 259 ((cfg.enableHTTPS == false) || (cfg.proxyHost == null) && (cfg.proxyPort == null)) 260 '' 261 sed -i /var/lib/nifi/conf/nifi.properties \ 262 -e 's|nifi.web.proxy.host=.*|nifi.web.proxy.host=|g' 263 '' 264 } 265 ${lib.optionalString ((cfg.initJavaHeapSize != null) && (cfg.maxJavaHeapSize != null)) '' 266 sed -i /var/lib/nifi/conf/bootstrap.conf \ 267 -e 's|java.arg.2=.*|java.arg.2=-Xms${(toString cfg.initJavaHeapSize)}m|g' \ 268 -e 's|java.arg.3=.*|java.arg.3=-Xmx${(toString cfg.maxJavaHeapSize)}m|g' 269 ''} 270 ${lib.optionalString ((cfg.initJavaHeapSize == null) && (cfg.maxJavaHeapSize == null)) '' 271 sed -i /var/lib/nifi/conf/bootstrap.conf \ 272 -e 's|java.arg.2=.*|java.arg.2=-Xms512m|g' \ 273 -e 's|java.arg.3=.*|java.arg.3=-Xmx512m|g' 274 ''} 275 ''; 276 ExecStart = "${cfg.package}/bin/nifi.sh start"; 277 ExecStop = "${cfg.package}/bin/nifi.sh stop"; 278 # User and group 279 User = cfg.user; 280 Group = cfg.group; 281 # Runtime directory and mode 282 RuntimeDirectory = "nifi"; 283 RuntimeDirectoryMode = "0750"; 284 # State directory and mode 285 StateDirectory = "nifi"; 286 StateDirectoryMode = "0750"; 287 # Logs directory and mode 288 LogsDirectory = "nifi"; 289 LogsDirectoryMode = "0750"; 290 # Proc filesystem 291 ProcSubset = "pid"; 292 ProtectProc = "invisible"; 293 # Access write directories 294 ReadWritePaths = [ cfg.initPasswordFile ]; 295 UMask = "0027"; 296 # Capabilities 297 CapabilityBoundingSet = ""; 298 # Security 299 NoNewPrivileges = true; 300 # Sandboxing 301 ProtectSystem = "strict"; 302 ProtectHome = true; 303 PrivateTmp = true; 304 PrivateDevices = true; 305 PrivateIPC = true; 306 PrivateUsers = true; 307 ProtectHostname = true; 308 ProtectClock = true; 309 ProtectKernelTunables = true; 310 ProtectKernelModules = true; 311 ProtectKernelLogs = true; 312 ProtectControlGroups = true; 313 RestrictAddressFamilies = [ "AF_INET AF_INET6" ]; 314 RestrictNamespaces = true; 315 LockPersonality = true; 316 MemoryDenyWriteExecute = false; 317 RestrictRealtime = true; 318 RestrictSUIDSGID = true; 319 RemoveIPC = true; 320 PrivateMounts = true; 321 # System Call Filtering 322 SystemCallArchitectures = "native"; 323 SystemCallFilter = [ 324 "~@cpu-emulation @debug @keyring @memlock @mount @obsolete @resources @privileged @setuid" 325 "@chown" 326 ]; 327 }; 328 }; 329 330 users.users = lib.mkMerge [ 331 (lib.mkIf (cfg.user == "nifi") { 332 nifi = { 333 group = cfg.group; 334 isSystemUser = true; 335 home = cfg.package; 336 }; 337 }) 338 (lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package nifiEnv ]) 339 ]; 340 341 users.groups = lib.optionalAttrs (cfg.group == "nifi") { 342 nifi = { }; 343 }; 344 }; 345}