at 23.11-pre 4.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.node-red; 7 defaultUser = "node-red"; 8 finalPackage = if cfg.withNpmAndGcc then node-red_withNpmAndGcc else cfg.package; 9 node-red_withNpmAndGcc = pkgs.runCommand "node-red" { 10 nativeBuildInputs = [ pkgs.makeWrapper ]; 11 } 12 '' 13 mkdir -p $out/bin 14 makeWrapper ${pkgs.nodePackages.node-red}/bin/node-red $out/bin/node-red \ 15 --set PATH '${lib.makeBinPath [ pkgs.nodePackages.npm pkgs.gcc ]}:$PATH' \ 16 ''; 17in 18{ 19 options.services.node-red = { 20 enable = mkEnableOption (lib.mdDoc "the Node-RED service"); 21 22 package = mkOption { 23 default = pkgs.nodePackages.node-red; 24 defaultText = literalExpression "pkgs.nodePackages.node-red"; 25 type = types.package; 26 description = lib.mdDoc "Node-RED package to use."; 27 }; 28 29 openFirewall = mkOption { 30 type = types.bool; 31 default = false; 32 description = lib.mdDoc '' 33 Open ports in the firewall for the server. 34 ''; 35 }; 36 37 withNpmAndGcc = mkOption { 38 type = types.bool; 39 default = false; 40 description = lib.mdDoc '' 41 Give Node-RED access to NPM and GCC at runtime, so 'Nodes' can be 42 downloaded and managed imperatively via the 'Palette Manager'. 43 ''; 44 }; 45 46 configFile = mkOption { 47 type = types.path; 48 default = "${cfg.package}/lib/node_modules/node-red/settings.js"; 49 defaultText = literalExpression ''"''${package}/lib/node_modules/node-red/settings.js"''; 50 description = lib.mdDoc '' 51 Path to the JavaScript configuration file. 52 See <https://github.com/node-red/node-red/blob/master/packages/node_modules/node-red/settings.js> 53 for a configuration example. 54 ''; 55 }; 56 57 port = mkOption { 58 type = types.port; 59 default = 1880; 60 description = lib.mdDoc "Listening port."; 61 }; 62 63 user = mkOption { 64 type = types.str; 65 default = defaultUser; 66 description = lib.mdDoc '' 67 User under which Node-RED runs.If left as the default value this user 68 will automatically be created on system activation, otherwise the 69 sysadmin is responsible for ensuring the user exists. 70 ''; 71 }; 72 73 group = mkOption { 74 type = types.str; 75 default = defaultUser; 76 description = lib.mdDoc '' 77 Group under which Node-RED runs.If left as the default value this group 78 will automatically be created on system activation, otherwise the 79 sysadmin is responsible for ensuring the group exists. 80 ''; 81 }; 82 83 userDir = mkOption { 84 type = types.path; 85 default = "/var/lib/node-red"; 86 description = lib.mdDoc '' 87 The directory to store all user data, such as flow and credential files and all library data. If left 88 as the default value this directory will automatically be created before the node-red service starts, 89 otherwise the sysadmin is responsible for ensuring the directory exists with appropriate ownership 90 and permissions. 91 ''; 92 }; 93 94 safe = mkOption { 95 type = types.bool; 96 default = false; 97 description = lib.mdDoc "Whether to launch Node-RED in --safe mode."; 98 }; 99 100 define = mkOption { 101 type = types.attrs; 102 default = {}; 103 description = lib.mdDoc "List of settings.js overrides to pass via -D to Node-RED."; 104 example = literalExpression '' 105 { 106 "logging.console.level" = "trace"; 107 } 108 ''; 109 }; 110 }; 111 112 config = mkIf cfg.enable { 113 users.users = optionalAttrs (cfg.user == defaultUser) { 114 ${defaultUser} = { 115 isSystemUser = true; 116 group = defaultUser; 117 }; 118 }; 119 120 users.groups = optionalAttrs (cfg.group == defaultUser) { 121 ${defaultUser} = { }; 122 }; 123 124 networking.firewall = mkIf cfg.openFirewall { 125 allowedTCPPorts = [ cfg.port ]; 126 }; 127 128 systemd.services.node-red = { 129 description = "Node-RED Service"; 130 wantedBy = [ "multi-user.target" ]; 131 after = [ "networking.target" ]; 132 environment = { 133 HOME = cfg.userDir; 134 }; 135 serviceConfig = mkMerge [ 136 { 137 User = cfg.user; 138 Group = cfg.group; 139 ExecStart = "${finalPackage}/bin/node-red ${pkgs.lib.optionalString cfg.safe "--safe"} --settings ${cfg.configFile} --port ${toString cfg.port} --userDir ${cfg.userDir} ${concatStringsSep " " (mapAttrsToList (name: value: "-D ${name}=${value}") cfg.define)}"; 140 PrivateTmp = true; 141 Restart = "always"; 142 WorkingDirectory = cfg.userDir; 143 } 144 (mkIf (cfg.userDir == "/var/lib/node-red") { StateDirectory = "node-red"; }) 145 ]; 146 }; 147 }; 148}