at 22.05-pre 4.6 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 "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 = "Node-RED package to use."; 27 }; 28 29 openFirewall = mkOption { 30 type = types.bool; 31 default = false; 32 description = '' 33 Open ports in the firewall for the server. 34 ''; 35 }; 36 37 withNpmAndGcc = mkOption { 38 type = types.bool; 39 default = false; 40 description = '' 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 = '' 51 Path to the JavaScript configuration file. 52 See <link 53 xlink:href="https://github.com/node-red/node-red/blob/master/packages/node_modules/node-red/settings.js"/> 54 for a configuration example. 55 ''; 56 }; 57 58 port = mkOption { 59 type = types.port; 60 default = 1880; 61 description = "Listening port."; 62 }; 63 64 user = mkOption { 65 type = types.str; 66 default = defaultUser; 67 description = '' 68 User under which Node-RED runs.If left as the default value this user 69 will automatically be created on system activation, otherwise the 70 sysadmin is responsible for ensuring the user exists. 71 ''; 72 }; 73 74 group = mkOption { 75 type = types.str; 76 default = defaultUser; 77 description = '' 78 Group under which Node-RED runs.If left as the default value this group 79 will automatically be created on system activation, otherwise the 80 sysadmin is responsible for ensuring the group exists. 81 ''; 82 }; 83 84 userDir = mkOption { 85 type = types.path; 86 default = "/var/lib/node-red"; 87 description = '' 88 The directory to store all user data, such as flow and credential files and all library data. If left 89 as the default value this directory will automatically be created before the node-red service starts, 90 otherwise the sysadmin is responsible for ensuring the directory exists with appropriate ownership 91 and permissions. 92 ''; 93 }; 94 95 safe = mkOption { 96 type = types.bool; 97 default = false; 98 description = "Whether to launch Node-RED in --safe mode."; 99 }; 100 101 define = mkOption { 102 type = types.attrs; 103 default = {}; 104 description = "List of settings.js overrides to pass via -D to Node-RED."; 105 example = literalExpression '' 106 { 107 "logging.console.level" = "trace"; 108 } 109 ''; 110 }; 111 }; 112 113 config = mkIf cfg.enable { 114 users.users = optionalAttrs (cfg.user == defaultUser) { 115 ${defaultUser} = { 116 isSystemUser = true; 117 group = defaultUser; 118 }; 119 }; 120 121 users.groups = optionalAttrs (cfg.group == defaultUser) { 122 ${defaultUser} = { }; 123 }; 124 125 networking.firewall = mkIf cfg.openFirewall { 126 allowedTCPPorts = [ cfg.port ]; 127 }; 128 129 systemd.services.node-red = { 130 description = "Node-RED Service"; 131 wantedBy = [ "multi-user.target" ]; 132 after = [ "networking.target" ]; 133 environment = { 134 HOME = cfg.userDir; 135 }; 136 serviceConfig = mkMerge [ 137 { 138 User = cfg.user; 139 Group = cfg.group; 140 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)}"; 141 PrivateTmp = true; 142 Restart = "always"; 143 WorkingDirectory = cfg.userDir; 144 } 145 (mkIf (cfg.userDir == "/var/lib/node-red") { StateDirectory = "node-red"; }) 146 ]; 147 }; 148 }; 149}