···
1
+
{ lib, pkgs, config, options, ... }:
4
+
cfg = config.services.nifi;
5
+
opt = options.services.nifi;
8
+
NIFI_OVERRIDE_NIFIENV = "true";
9
+
NIFI_HOME = "/var/lib/nifi";
10
+
NIFI_PID_DIR = "/run/nifi";
11
+
NIFI_LOG_DIR = "/var/log/nifi";
14
+
envFile = pkgs.writeText "nifi.env" (lib.concatMapStrings (s: s + "\n") (
15
+
(lib.concatLists (lib.mapAttrsToList (name: value:
16
+
if value != null then [
17
+
"${name}=\"${toString value}\""
21
+
nifiEnv = pkgs.writeShellScriptBin "nifi-env" ''
30
+
enable = lib.mkEnableOption "Apache NiFi";
32
+
package = lib.mkOption {
33
+
type = lib.types.package;
34
+
default = pkgs.nifi;
35
+
defaultText = lib.literalExpression "pkgs.nifi";
36
+
description = "Apache NiFi package to use.";
39
+
user = lib.mkOption {
40
+
type = lib.types.str;
42
+
description = "User account where Apache NiFi runs.";
45
+
group = lib.mkOption {
46
+
type = lib.types.str;
48
+
description = "Group account where Apache NiFi runs.";
51
+
enableHTTPS = lib.mkOption {
52
+
type = lib.types.bool;
54
+
description = "Enable HTTPS protocol. Don`t use in production.";
57
+
listenHost = lib.mkOption {
58
+
type = lib.types.str;
59
+
default = if cfg.enableHTTPS then "0.0.0.0" else "127.0.0.1";
60
+
defaultText = lib.literalExpression ''
61
+
if config.${opt.enableHTTPS}
65
+
description = "Bind to an ip for Apache NiFi web-ui.";
68
+
listenPort = lib.mkOption {
69
+
type = lib.types.int;
70
+
default = if cfg.enableHTTPS then 8443 else 8080;
71
+
defaultText = lib.literalExpression ''
72
+
if config.${opt.enableHTTPS}
76
+
description = "Bind to a port for Apache NiFi web-ui.";
79
+
proxyHost = lib.mkOption {
80
+
type = lib.types.nullOr lib.types.str;
81
+
default = if cfg.enableHTTPS then "0.0.0.0" else null;
82
+
defaultText = lib.literalExpression ''
83
+
if config.${opt.enableHTTPS}
87
+
description = "Allow requests from a specific host.";
90
+
proxyPort = lib.mkOption {
91
+
type = lib.types.nullOr lib.types.int;
92
+
default = if cfg.enableHTTPS then 8443 else null;
93
+
defaultText = lib.literalExpression ''
94
+
if config.${opt.enableHTTPS}
98
+
description = "Allow requests from a specific port.";
101
+
initUser = lib.mkOption {
102
+
type = lib.types.nullOr lib.types.str;
104
+
description = "Initial user account for Apache NiFi. Username must be at least 4 characters.";
107
+
initPasswordFile = lib.mkOption {
108
+
type = lib.types.nullOr lib.types.path;
110
+
example = "/run/keys/nifi/password-nifi";
111
+
description = "nitial password for Apache NiFi. Password must be at least 12 characters.";
114
+
initJavaHeapSize = lib.mkOption {
115
+
type = lib.types.nullOr lib.types.int;
118
+
description = "Set the initial heap size for the JVM in MB.";
121
+
maxJavaHeapSize = lib.mkOption {
122
+
type = lib.types.nullOr lib.types.int;
125
+
description = "Set the initial heap size for the JVM in MB.";
130
+
config = lib.mkIf cfg.enable {
132
+
{ assertion = cfg.initUser!=null || cfg.initPasswordFile==null;
134
+
<option>services.nifi.initUser</option> needs to be set if <option>services.nifi.initPasswordFile</option> enabled.
137
+
{ assertion = cfg.initUser==null || cfg.initPasswordFile!=null;
139
+
<option>services.nifi.initPasswordFile</option> needs to be set if <option>services.nifi.initUser</option> enabled.
142
+
{ assertion = cfg.proxyHost==null || cfg.proxyPort!=null;
144
+
<option>services.nifi.proxyPort</option> needs to be set if <option>services.nifi.proxyHost</option> value specified.
147
+
{ assertion = cfg.proxyHost!=null || cfg.proxyPort==null;
149
+
<option>services.nifi.proxyHost</option> needs to be set if <option>services.nifi.proxyPort</option> value specified.
152
+
{ assertion = cfg.initJavaHeapSize==null || cfg.maxJavaHeapSize!=null;
154
+
<option>services.nifi.maxJavaHeapSize</option> needs to be set if <option>services.nifi.initJavaHeapSize</option> value specified.
157
+
{ assertion = cfg.initJavaHeapSize!=null || cfg.maxJavaHeapSize==null;
159
+
<option>services.nifi.initJavaHeapSize</option> needs to be set if <option>services.nifi.maxJavaHeapSize</option> value specified.
164
+
warnings = lib.optional (cfg.enableHTTPS==false) ''
165
+
Please do not disable HTTPS mode in production. In this mode, access to the nifi is opened without authentication.
168
+
systemd.tmpfiles.rules = [
169
+
"d '/var/lib/nifi/conf' 0750 ${cfg.user} ${cfg.group}"
170
+
"L+ '/var/lib/nifi/lib' - - - - ${cfg.package}/lib"
174
+
systemd.services.nifi = {
175
+
description = "Apache NiFi";
176
+
after = [ "network.target" ];
177
+
wantedBy = [ "multi-user.target" ];
180
+
path = [ pkgs.gawk ];
184
+
PIDFile = "/run/nifi/nifi.pid";
185
+
ExecStartPre = pkgs.writeScript "nifi-pre-start.sh" ''
188
+
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')
189
+
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')
190
+
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')
191
+
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')
192
+
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')
193
+
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')
194
+
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')
195
+
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')
196
+
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')
197
+
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')
198
+
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')
199
+
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')
200
+
${lib.optionalString ((cfg.initUser != null) && (cfg.initPasswordFile != null)) ''
201
+
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})
203
+
${lib.optionalString (cfg.enableHTTPS == false) ''
204
+
sed -i /var/lib/nifi/conf/nifi.properties \
205
+
-e 's|nifi.remote.input.secure=.*|nifi.remote.input.secure=false|g' \
206
+
-e 's|nifi.web.http.host=.*|nifi.web.http.host=${cfg.listenHost}|g' \
207
+
-e 's|nifi.web.http.port=.*|nifi.web.http.port=${(toString cfg.listenPort)}|g' \
208
+
-e 's|nifi.web.https.host=.*|nifi.web.https.host=|g' \
209
+
-e 's|nifi.web.https.port=.*|nifi.web.https.port=|g' \
210
+
-e 's|nifi.security.keystore=.*|nifi.security.keystore=|g' \
211
+
-e 's|nifi.security.keystoreType=.*|nifi.security.keystoreType=|g' \
212
+
-e 's|nifi.security.truststore=.*|nifi.security.truststore=|g' \
213
+
-e 's|nifi.security.truststoreType=.*|nifi.security.truststoreType=|g' \
214
+
-e '/nifi.security.keystorePasswd/s|^|#|' \
215
+
-e '/nifi.security.keyPasswd/s|^|#|' \
216
+
-e '/nifi.security.truststorePasswd/s|^|#|'
218
+
${lib.optionalString (cfg.enableHTTPS == true) ''
219
+
sed -i /var/lib/nifi/conf/nifi.properties \
220
+
-e 's|nifi.remote.input.secure=.*|nifi.remote.input.secure=true|g' \
221
+
-e 's|nifi.web.http.host=.*|nifi.web.http.host=|g' \
222
+
-e 's|nifi.web.http.port=.*|nifi.web.http.port=|g' \
223
+
-e 's|nifi.web.https.host=.*|nifi.web.https.host=${cfg.listenHost}|g' \
224
+
-e 's|nifi.web.https.port=.*|nifi.web.https.port=${(toString cfg.listenPort)}|g' \
225
+
-e 's|nifi.security.keystore=.*|nifi.security.keystore=./conf/keystore.p12|g' \
226
+
-e 's|nifi.security.keystoreType=.*|nifi.security.keystoreType=PKCS12|g' \
227
+
-e 's|nifi.security.truststore=.*|nifi.security.truststore=./conf/truststore.p12|g' \
228
+
-e 's|nifi.security.truststoreType=.*|nifi.security.truststoreType=PKCS12|g' \
229
+
-e '/nifi.security.keystorePasswd/s|^#\+||' \
230
+
-e '/nifi.security.keyPasswd/s|^#\+||' \
231
+
-e '/nifi.security.truststorePasswd/s|^#\+||'
233
+
${lib.optionalString ((cfg.enableHTTPS == true) && (cfg.proxyHost != null) && (cfg.proxyPort != null)) ''
234
+
sed -i /var/lib/nifi/conf/nifi.properties \
235
+
-e 's|nifi.web.proxy.host=.*|nifi.web.proxy.host=${cfg.proxyHost}:${(toString cfg.proxyPort)}|g'
237
+
${lib.optionalString ((cfg.enableHTTPS == false) || (cfg.proxyHost == null) && (cfg.proxyPort == null)) ''
238
+
sed -i /var/lib/nifi/conf/nifi.properties \
239
+
-e 's|nifi.web.proxy.host=.*|nifi.web.proxy.host=|g'
241
+
${lib.optionalString ((cfg.initJavaHeapSize != null) && (cfg.maxJavaHeapSize != null))''
242
+
sed -i /var/lib/nifi/conf/bootstrap.conf \
243
+
-e 's|java.arg.2=.*|java.arg.2=-Xms${(toString cfg.initJavaHeapSize)}m|g' \
244
+
-e 's|java.arg.3=.*|java.arg.3=-Xmx${(toString cfg.maxJavaHeapSize)}m|g'
246
+
${lib.optionalString ((cfg.initJavaHeapSize == null) && (cfg.maxJavaHeapSize == null))''
247
+
sed -i /var/lib/nifi/conf/bootstrap.conf \
248
+
-e 's|java.arg.2=.*|java.arg.2=-Xms512m|g' \
249
+
-e 's|java.arg.3=.*|java.arg.3=-Xmx512m|g'
252
+
ExecStart = "${cfg.package}/bin/nifi.sh start";
253
+
ExecStop = "${cfg.package}/bin/nifi.sh stop";
257
+
# Runtime directory and mode
258
+
RuntimeDirectory = "nifi";
259
+
RuntimeDirectoryMode = "0750";
260
+
# State directory and mode
261
+
StateDirectory = "nifi";
262
+
StateDirectoryMode = "0750";
263
+
# Logs directory and mode
264
+
LogsDirectory = "nifi";
265
+
LogsDirectoryMode = "0750";
267
+
ProcSubset = "pid";
268
+
ProtectProc = "invisible";
269
+
# Access write directories
270
+
ReadWritePaths = [ cfg.initPasswordFile ];
273
+
CapabilityBoundingSet = "";
275
+
NoNewPrivileges = true;
277
+
ProtectSystem = "strict";
278
+
ProtectHome = true;
280
+
PrivateDevices = true;
282
+
PrivateUsers = true;
283
+
ProtectHostname = true;
284
+
ProtectClock = true;
285
+
ProtectKernelTunables = true;
286
+
ProtectKernelModules = true;
287
+
ProtectKernelLogs = true;
288
+
ProtectControlGroups = true;
289
+
RestrictAddressFamilies = [ "AF_INET AF_INET6" ];
290
+
RestrictNamespaces = true;
291
+
LockPersonality = true;
292
+
MemoryDenyWriteExecute = false;
293
+
RestrictRealtime = true;
294
+
RestrictSUIDSGID = true;
296
+
PrivateMounts = true;
297
+
# System Call Filtering
298
+
SystemCallArchitectures = "native";
299
+
SystemCallFilter = [ "~@cpu-emulation @debug @keyring @memlock @mount @obsolete @resources @privileged @setuid" "@chown" ];
303
+
users.users = lib.mkMerge [
304
+
(lib.mkIf (cfg.user == "nifi") {
307
+
isSystemUser = true;
308
+
home = cfg.package;
311
+
(lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package nifiEnv ])
314
+
users.groups = lib.optionalAttrs (cfg.group == "nifi") {