Exposing Node-RED to the Internet

Background

Like many of you reading this, I run Node-RED on a Raspberry Pi. My primary reasons for selecting a Raspberry Pi over other solutions are primarily cost and convenience. For my latest project, I am using a Raspberry Pi 4 (that I purchased as part of the CanaKit Raspberry Pi 4 Starter Kit) that sits in my home office running 24/7.

Recently, I decided to make use of a Node-RED Dashboard to display the status of various sensors around my house (e.g. garage door sensors, a sensor on our deep freeze, a temperature sensor where our water pipes come in the house, etc.). I’m still adding sensors here and there and also playing around with Node-RED options but here’s a quick glance at what my dashboard currently looks like:

Node-RED Dashboard
Node-RED Dashboard

One of the great things about Node-RED Dashboards is that they render really well on mobile devices, essentially stacking each of the groups on top of each other. And, as long as I am on my home network, it all works really well on my phone. However, I wanted to be able to view my dashboard while disconnected from my home network. I mean, it’s called the internet of things for a reason, rights?

Accessing the Dashboard via the Internet – Options

When it comes to accessing a device on your home network from another device connected to the internet (but not your home network), there are a few basic options:

  1. Hosting the application (in this case, Node-RED) in a cloud provider such as AWS or Azure. Obviously, we want to run Node-RED on a Raspberry Pi, so this option doesn’t make sense.
  2. Utilize a VPN for access. This would require installing a VPN server on your Raspberry Pi. You would also need to install a VPN client on each device that would be used to access the Raspberry Pi – e.g. your mobile phone as well as others in your family, if desired. While this will work, it will not be as easy and convenient as popping your favorite mobile web browser and navigating to your Node-RED Dashboard URL. We can do better!
  3. As hinted to above, exposing Node-RED from your Raspberry Pi on the internet will provide an easy, natural experience for viewing the dashboard. Viewing the dashboard on your mobile phone wouldn’t be any different than viewing your bank account. This is the option we want to go with!

Exposing Node-RED to the Internet

Now that we’ve decided to expose Node-RED, running on our Raspberry Pi, directly to the internet, we need to do it properly to ensure our Raspberry Pi is secure. I’ve detailed the steps I went through below to expose and secure my Raspberry Pi.

CAVEAT: This might look overwhelming but, if you take it step by step, it should go relatively smoothly. I worked on the following steps off and on over the course of about two days before completion. Your mileage may vary. 😁

Configure Node-RED to require user authentication

One of the first things you’ll want to do when exposing a secure website to the internet is to require user authentication. While I want the convenience for me and my family to easily access my Node-RED Dashboard over the internet, I don’t want just anyone being able to view it!

Setting up user authentication for Node-RED is fairly straight forward as this capability is built into the product and simply needs to be “turned on” with a handful of configuration settings. Refer to the official docs for Securing Node-RED for detailed instructions and pay special attention to the section Username/password based authentication. Here, you will see how to create a user name (e.g. “admin”, “george”, etc.) and an associated, hashed password.

NOTE: The docs show how to password-protect the Node-RED Admin site (which is where you create the various Node-RED flows); You will also need to create a user name and hashed password (following the same process) for the Node-RED Dashboard. For this, you will need to make similar configuration changes to the httpNodeAuth section within the settings.js file just as you did for the adminAuth section.

Here’s a screenshot of the appropriate sections in my settings.js file:

settings.js file
settings.js File

Purchase a domain name and SSL certificate.
You will want to purchase a domain name for your Node-RED site. I have used GoDaddy as my internet domain registrar for years so, naturally, I purchased my new domain from them. I went with the .app top level domain because: a) it requires a certificate (this is enforced when you navigate to a *.app site; If you prefix with HTTP, it will automatically redirect to HTTPS) and, b) GoDaddy provides an SSL certificate when purchasing a .app domain name. You can read more about GoDaddy’s offering here. Also, instructions for setting up your GoDaddy SSL certificate can be found here. Finally, if you are using a certificate from GoDaddy, you will need to create a Certificate Signing Request (CSR). You can find instructions on how to do this here.

NOTE: You do not have to utilize a .app domain, nor do you have to use GoDaddy to purchase your domain name. Any domain name, purchased from any internet domain registrar will work just fine. You’ll also need to ensure you purchase an SSL certificate as well to match your new domain name.

Configure Node-RED to use a certificate

Now that you have an SSL certificate, you will need to configure Node-RED to utilize the certificate for encryption. As you might expect, this is configured within the same settings.js file you configured above. Rather than repeat everything in this post, you can read Mat’s great write up here on implementing SSL certificates within Node-RED. Ultimately, it comes down to storing a key and certificate file on your Raspberry Pi and telling Node-RED where they are located. For example, my config looks something like this:

Key and Certificate File Locations
Key and Certificate File Locations

Point your newly-purchased domain to your external (WAN) IP address

OK, we’re getting close! Just a few more steps and we’ll be finished.

Now that you have a shiny, new domain name, you need to update it to point to your home network’s public IP address. To do this, you’ll need your public IP address. There are several ways to obtain this but one of the easiest is to simply go to: https://api.ipify.org/

Within GoDaddy, if you go navigate to your newly-purchased domain and select the Manage DNS options, you’ll see something like this:

DNS Management
DNS Management

On this page, you’ll want to edit the ‘A’ record (or add one if it doesn’t exist) to point to your public IP address. Once updated, your new domain will direct traffic to your public IP address. NOTE: This could take several hours to take effect. Flushing your local DNS cache might be helpful when making changes to your DNS records.

Set a Static IP Address for Your Raspberry Pi

For the next step to work reliably, you’ll need to set a static IP Address for your Raspberry Pi. This can be accomplished within your Wi-Fi (or other) network router. I use Google WiFi, so I’ll provide instructions for that router. You should be able to find instructions for setting a static IP address for your particular router with a simple internet search.

To set a static IP address within Google WiFi:

Open the Google WiFi mobile app.

Tap on Devices and locate your Raspberry Pi in the list. Mine had Raspberry Pi in the default name, so it was easy to locate. You can also show MAC Addresses if it helps locate the device (turn this option on by clicking the “…” menu in the upper right). Once located, tap on the device.

Click on the “…” menu in the upper right and select the Reserve IP option.

Tap Next and then Done.

From now on, any time your Raspberry Pi is rebooted, the IP address will remain the same. 

Forward External Traffic to Node-RED

Next, you will need to forward traffic to your public IP address to Node-RED. This is accomplished by setting up port-forwarding rules within your network router. Here are the instructions for setting up port forwarding on Google WiFi. You can find specific instructions for your router via an internet search. 

To setup port forwarding within Google WiFi:

  1. Open the Google WiFi mobile app.
  2. Tap on Devices and locate your Raspberry Pi in the list. Mine had Raspberry Pi in the default name, so it was easy to locate. You can also show MAC Addresses if it helps locate the device (turn this option on by clicking the “…” menu in the upper right). Once located, tap on the device.
  3. Click on the “…” menu in the upper right and select the Set up IPv4 port forwarding option.
  4. Specify the internal port for your Node-RED server (default is 1880).
  5. Specify the external port you want to use to access your Node-RED server. I used 443 since the site is encrypted and HTTPS will default to 443 by default.
  6. Select TCP and UDP (I’m not really sure if UDP is used but figured why not).
  7. Tap on Done.

At this point, all traffic over port 443 going to your public IP address will be forwarded to your Node-RED server. Nice! 

Setup Dynamic DNS

Much like the IP address for our Raspberry Pi could change between reboots (not now, however), it’s possible your internet service provider (ISP) might change your public IP address from time to time. In Step 4 above, we pointed our new domain to our public IP address. If this IP address changes, you would no longer be able to access your Node-RED site via the domain name. What we need to do, is update our DNS record if our public IP address changes.

Fortunately, this is not that difficult to accomplish with the combination of a (relatively) simple Bash script and a Cron job that runs every so often on your Raspberry Pi.

I based my script off this blog post and setup a Cron job that runs this script every 10 minutes. The Cron job passes in my domain name, DNS host (in this case, ‘@’), my GoDaddy API Key and API Secret. My script looks like this:

#!/bin/bash

domain=$1
host=$2
APIKey=$3
APISecret=$4

WanIP=`curl -s "https://api.ipify.org"`

GDIP=`curl -s -X GET -H "Authorization: sso-key ${APIKey}:${APISecret}" "https://api.godaddy.com/v1/domains/${domain}/records/A/${host}" | cut -d'[' -f 2 | cut -d']' -f 1 | jq -r '.data'`

if [ "$WanIP" != "$GDIP" -a "$WanIP" != "" ]; then
        curl -s -X PUT "https://api.godaddy.com/v1/domains/${domain}/records/A/${host}" -H "Authorization: sso-key ${APIKey}:${APISecret}" -H "Content-Type: application/json" -d "[{\"data\": \"${WanIP}\"}]"
fi

If you are not using GoDaddy as your internet domain registrar, you should check to see if your registrar offers an API. If it does, then you should be able to modify the above script to work with your registrar. Otherwise, there are plenty of Dynamic DNS services available – some for free and some for $$$.

Bonus Section

Now that you can access your Node-RED server securely over the internet, you might want to change a couple default settings to make the experience a little nicer. For example, I wanted to be able to navigate directly to my new domain and have the Node-RED Dashboard display. For example: https://mydomain.app — instead of https://mydomain.app/ui. This can be configured easily within the Node-RED settings.js file by modifying: ui: { path: “”}. This is what mine looks like in my settings file:

UI Path

Likewise, I wanted the Admin screen to be served at https://mydomain.app/admin so I modified the httpAdminRoot setting as follows:

Admin Root Path

These last tweaks provide for a very natural experience when viewing the Node-RED Dashboard on my mobile phone.

Finally

I recreated most of the above notes from a few notes that I had taken while I was doing the research for this and also from memory. As you can see, there are quite a few steps listed above and it’s entirely possible I’ve forgotten a step or two. It’s also possible that there might be better/easier ways to do this or better references. If you have thoughts on how to improve this write up, please comment below and I will update accordingly. Also, please let everyone know about your experience and any tips you might have to offer. I love learning new ways to accomplish things!

Thanks!

Related Articles

You might find these Node-RED articles interesting:

Related Posts