Skip to content

NGINX & Proxying Node RED

Julian Knight edited this page Jun 26, 2022 · 3 revisions

Please see the updated article in the Tech Docs.


This article assumes the use of Debian Buster (10). It should probably also work on Rasbian Buster. It also assumes that you already have Node-RED installed and working (and therefore Node.js) and a working uibuilder node.

WARNING This configuration guide does NOT cover SECURITY of your server. Do not expose a server to the Internet without having a properly configured firewall and until you have hardened the OS configuration of your server.

Step 1: Install NGINX

# Update the catalogue of installable apps
sudo apt update
# Get all installed aps up-to-date
sudo apt upgrade

Next follow the instructions at https://nginx.org/en/linux_packages.html#Debian to make sure that you get a decent version of NGINX. Note that I don't personally advise installing the version that is included in the standard Debian libraries as these are usually quite a long way behind current.

Choose the mainline version for the latest features (might occasionally be slightly less stable) or the stable version for production use.

As at the time of writing this:

# Install the prerequisites:
sudo apt install curl gnupg2 ca-certificates lsb-release

# To set up the apt repository for stable nginx packages, run the following command:
echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list

# If you would like to use mainline nginx packages, run the following command instead:
#echo "deb http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list

# Set up repository pinning to prefer our packages over distribution-provided ones:
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx

# Next, import an official nginx signing key so apt could verify the packages authenticity. Fetch the key:
curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key

# Verify that the downloaded file contains the proper key:
gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key

# The output should contain the full fingerprint 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 as follows:
#
#  pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
#        573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
#  uid                      nginx signing key <[email protected]>

# Finally, move the key to apt trusted key storage (note the "asc" file extension change):
sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc

# To install nginx, run the following commands:
sudo apt update
sudo apt install nginx

You should now be able to see that NGINX is running:

# Show the status
sudo systemctl status nginx

# Show the log
sudo journalctl -u nginx

# Restart/Start/Stop
sudo systemctl restart nginx

At this point, you can open the default web page at http://<server-ip-or-domain-name>/.

The configuration for NGINX lives at /etc/nginx/. There is a default nginx.conf file there that tells you where logs are stored should you need them though using journalctl is generally preferable for viewing. It is recommended to leave this file alone.

There is also a /etc/nginx/conf.d/default.conf file that defines a default simple root website. You can either repurpose this if you don't want to create any other sites, or you can create your own .conf file.

NOTE that, by default, NGINX runs as user and group nginx. You should create files owned by this user/group when you want the server to serve them. Configuration files must be owned by root:root.

Step 2: Create a Virtual Server Configuration for Node-RED

In this example, we will create a config file /etc/nginx/conf.d/nodered.conf. This will leave the default root site as it is, if you aren't using a default root site, you should remove that configuration.

I will assume the following Node-RED settings that illustrate a number of features:

  • Node-RED is running under the user id that you log into the server with. Note that this is a bad idea for production use, particularly if exposing to the Internet, move Node-RED to use its own user/group and make sure that all files are owned by that user/group. Don't allow that user id to log in to the server.
  • The Node-RED Editor page is moved to http://<server-ip-or-domain-name>:1880/red
  • The Node-RED Dashboard page is: http://<server-ip-or-domain-name>:1880/ui
  • Node-RED is installed locally not globally to ~/nrmain, the userDir folder is set to ~/nrmain/data.
  • The Node-RED static resource folder is in ~/nrmain/data/public/

/etc/nginx/conf.d/nodered.conf

This file should be owned by root:root (use sudo to edit it).

#proxy for node-red @ port :1880
# Redirect all http to https
server {
        listen 80 default_server;
        listen [::]:80;

        server_name _;

        return 301 https://$host$request_uri;
}

# Proxy Node-RED
server {
        # Ports to listen on.
        listen 443 ssl http2;
        listen [::]:443 ssl http2 ipv6only=on;

        # If you want to limit this config to specific (sub)domain names:
        server_name example.com nr.example.com;

        # Specify the public cert and private key
        ssl_certificate     /path/to/fullchain.cer;
        ssl_certificate_key /path/to/privatekey.key;
        # Require safe TLS protocols only
        ssl_protocols TLSv1.1 TLSv1.2;
        # Only use secure encryption ciphers
        ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
        # Configure for Strict Transport Security (HSTS)
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

        #location = /robots.txt {
        #       add_header  Content-Type  text/plain;
        #       return 200 "User-agent: *\nDisallow: /\n";
        #}

        # Specify the actual URL path to proxy
        # NOTE: To change this to something other than `/`, you have to add a rewrite rule:
        #           # Assuming you want to use `location /red/`
        #           rewrite ^/red/(.*)$ /$1 break;
        location / {
                # Change the IP address and port to match your instance of Node-RED
                # Note that you don't need to make Node-RED serve https if it is on the same
                #      server as NGINX
                proxy_pass https://127.0.0.1:1880;

                # If using a location other than just `/`, we need to rewrite all of the /red/ URLS to remove the `red` part
		# If we don't, the node.js server won't understand the requests
                #rewrite ^/red/(.*)$ /$1 break;

		# If you only want to expose the Node-RED Dashboard instead of the whole of Node-RED ...
		# of course, you can do this for any Node-RED path, such as a specific uibuiler URL.
		#rewrite ^/(.*)$ /ui/$1 break;

                #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;

        }

        # You can create multiple locations with different paths.
        # You will need to do this if you are running uibuilder on its own webserver (and so with a different port).
}

After editing the file, check for configuration errors: sudo nginx -t, restart NGINX: sudo systemctl restart nginx and check that that it started OK: sudo journalctl -u nginx.

Final Notes

  1. Remember that, if you are proxying URL's, not all of the links in the Node-RED editor will work. You will have to mentally translate them to their new locations.

  2. If you are using proxying to help give additional security, remember to block access to ALL TCP PORTS except the specific ones you have proxied. Do this at the router/firewall level if you still need to give people on your internal network access to the other ports.

References

Clone this wiki locally