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