Jump to content

Node-red

From NixOS Wiki

Node-red

Node-red describeds itself as a "Low-code programming for event-driven applications", where you can connect nodes (that you can possibly obtain directly from a large list of npm packages) to automatize many different tasks.

Standalone run

You can simply install and run the application locally like:

$ nix-shell -p node-red
$ node-red
… http://127.0.0.1:1880/
…

and you will see the address of the website that is loaded in the log, typically http://127.0.0.1:1880/. Just open the link, and start to use node-red (you may also want to check the command line options of node-red to configure it further). Note that if you want to imperatively install new nodes, you may need to enable nix-ld if you run NixOS.

As a publicly accessible website

If you want to configure it as a permanent, always active service, on your own computer, you can configure the services.node-red module. Below, we describe a more advanced usecase where you also want to make the service available online, behind an Nginx server in charge of configuring automatically the https certificate.

{ lib, pkgs, config, ... }:
let
  cfg = config.services.node-red;
in
{
  services.nginx = {
    virtualHosts."YOURDOMAIN.com" = {
      forceSSL = true; # Enable and force https
      enableACME = true; # Automatically get a Let's Encrypt certificate 
      locations."/" = {
        proxyPass = "http://localhost:${toString cfg.port}";
        # This fixes WS errors, inspired by
        # https://github.com/meeki007/node-red-server-howto-guide/blob/master/README.md
        extraConfig = ''
          #Defines the HTTP protocol version for proxying by default it it set to 1.0.
          #For Websockets and keepalive connections you need to use the version 1.1
          proxy_http_version  1.1;
          
          #Sets conditions under which the response will not be taken from a cache.
          proxy_cache_bypass  $http_upgrade;
          
          #These header fields are required if your application is using Websockets
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          
          #The $host variable in the following order of precedence contains:
          #hostname from the request line, or hostname from the Host request header field
          #or the server name matching a request.
          proxy_set_header Host $host;
          
          #Forwards the real visitor remote IP address to the proxied server
          proxy_set_header X-Real-IP $remote_addr;
          
          #A list containing the IP addresses of every server the client has been proxied through
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          
          #When used inside an HTTPS server block, each HTTP response from the proxied server is rewritten to HTTPS.
          proxy_set_header X-Forwarded-Proto $scheme;
          
          #Defines the original host requested by the client.
          proxy_set_header X-Forwarded-Host $host;
          
          #Defines the original port requested by the client.
          proxy_set_header X-Forwarded-Port $server_port;      
        '';
      };
    };
  };
  
  services.node-red = {
    enable = true;
    # Do NOT open this port, nginx will automatically forward to it
    port = 1880;
    withNpmAndGcc = true; # Allow imperative download of nodes. Need to enable nix-ld, see below
    # I just downloaded the file from
    # https://github.com/node-red/node-red/blob/master/packages/node_modules/node-red/settings.js
    # and I added for instance a user in the configuration, changed the
    # contextStorage, and enabled project. I can't use "define" (that uses -D)
    # since for what I know it does not support nested lists of users, and is also less
    # practical than uncommenting a config file.
    configFile = ./node-red-settings.js;
  };

  # If you want to imperatively install most npm packages, you will need nix-ld since npm is typically
  # not very pure (to say the least)
  programs.nix-ld.enable = true;
  systemd.services.node-red = {
    path = with pkgs; [
      # git is needed for projects, but systemd resets the path so we need to add it back
      git
      # needed by nodejs to install for instance node-red-dashboard (or "error syscall spawn sh")
      bash
      # Add here any other program needed by the npm packages you want to install
    ];
    environment = {
      # environment variables are removed, so we need to specify nix-ld environment here
      NIX_LD = lib.fileContents "${pkgs.stdenv.cc}/nix-support/dynamic-linker";
      NIX_LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath [
        # List by default
        zlib
        zstd
        stdenv.cc.cc
        curl
        openssl
        attr
        libssh
        bzip2
        libxml2
        acl
        libsodium
        util-linux
        xz
        systemd
      ];
    };
  };
  
}