// Tutorial //

How to Connect Your Internet of Things with Node-RED on Ubuntu 16.04

Published on September 23, 2016
Default avatar
By Brian Boucheron
Developer and author at DigitalOcean.
How to Connect Your Internet of Things with Node-RED on Ubuntu 16.04

Introduction

Node-RED is a switchboard for the Internet of Things, a visual tool that helps you connect your favorite apps, websites, and hardware together to do new and useful things. Most often compared to IFTTT or the late Yahoo Pipes, Node-RED has a much more powerful and flexible interface, and a large open source community creating nodes to interact with a wide variety of apps and services.

In this tutorial, we’ll install Node.js and Node-RED, get an SSL certificate from Let’s Encrypt, and use Nginx to handle secure connections for Node-RED.

Prerequisites

To follow this tutorial, you will need:

  • One Ubuntu 16.04 server with a non-root sudo user and basic firewall set up by following this Ubuntu 16.04 sever setup tutorial. For this tutorial, we’ll use a user called sammy, but of course you can choose whatever you like and substitute as needed.

  • The web server Nginx installed, with the firewall updated to allow traffic on ports 80 and 443 (Nginx Full), as explained in How To Install Nginx on Ubuntu 16.04

  • A domain name pointed at your server, as described in How To Set Up a Host Name with DigitalOcean. This tutorial will use node-red.example.com throughout.

  • Let’s Encrypt installed, and a certificate generated for the domain you configured above. How To Secure Nginx with Let’s Encrypt on Ubuntu 16.04 will walk you through the necessary steps. You can ignore the steps regarding Nginx configuration (steps 3–5), as we’ll cover that here. Just make sure you get a certificate successfully issued, and set up the cron job to handle automatic renewals.

Step 1 — Installing Node.js and npm

Ubuntu 16.04 makes it easy to install the latest long term support (LTS) release of Node.js because it’s included in the default repository.

  1. sudo apt-get install nodejs-legacy

The command installs Node.js v4.2.x LTS (long term support), which means the Node.js Foundation will continue to support this version for 30 months from its release date of October 12, 2015.

Note: It’s important to install the -legacy version of the package because Node-RED’s startup scripts expect your Node.js binary to be named node, but the standard package uses nodejs instead. This is due to a naming conflict with a preexisting package.

Verify that the installation was successful by checking the version.

  1. node -v

You’ll see Node.js output its version number:

Output
v4.2.6

Node Package Manager (npm) helps you install and manage Node.js software packages, and we’ll use it to install Node-RED. Install npm using apt-get.

  1. sudo apt-get install npm

To verify the install was successful, ask npm to print its version information:

  1. npm -v
Output
3.5.2

If it prints a version number without error, we can continue on to our next step, where we’ll use npm to install Node-RED itself.

Step 2 — Installing Node-RED

Use npm to install node-red and a helper utility called node-red-admin.

  1. sudo npm install -g --unsafe-perm node-red node-red-admin

npm normally installs its packages into your current directory. Here, we use the -g flag to install packages ‘globally’ so they’re placed in standard system locations such as /usr/local/bin. The --unsafe-perm flag helps us avoid some errors that can pop up when npm tries to compile native modules (modules written in a compiled language such as C or C++ vs. JavaScript).

After a bit of downloading and file shuffling, you’ll be returned to the normal command line prompt. Let’s test our install.

First, we’ll need to open up a port on our firewall. Node-RED defaults to using port 1880, so let’s allow that.

  1. sudo ufw allow 1880

And now launch Node-RED itself. No sudo is necessary, as port 1880 is high enough to not require root privileges.

  1. node-red

Some “Welcome to Node-RED” messages will print to the terminal. On your computer, point a web browser to port 1880 of the server. In our example, that’s http://node-red.example.com:1880. The main admin interface of Node-RED will load.

Node-RED's main editing interface

If it worked, you can type CTRL+C in your terminal to shut down Node-RED and return to the command prompt. We’ve installed Node-RED successfully and tested it out, so next, we’ll set it up to launch during system startup.

Step 3 — Launching Node-RED on Startup

In order to start Node-RED automatically on startup, we’ll need to install a node-red.service file instead of the more traditional init script. This is because Ubuntu 16.04 is the first LTS release that uses systemd for its init system. You can find a summary of this and other Ubuntu 16.04 changes in What’s New in Ubuntu 16.04.

Open a blank service file called node-red.service.

  1. sudo nano /etc/systemd/system/node-red.service

Copy and paste in the following, then save and close the file.

/etc/systemd/system/node-red.service
[Unit]
Description=Node-RED
After=syslog.target network.target

[Service]
ExecStart=/usr/local/bin/node-red-pi --max-old-space-size=128 -v
Restart=on-failure
KillSignal=SIGINT

# log output to syslog as 'node-red'
SyslogIdentifier=node-red
StandardOutput=syslog

# non-root user to run as
WorkingDirectory=/home/sammy/
User=sammy
Group=sammy

[Install]
WantedBy=multi-user.target

A full explanation of systemd service files is beyond this tutorial, but you can learn more by reading Systemd Essentials: Working with Services, Units, and the Journal.

That said, let’s break down some of the sections in our service file:

/etc/systemd/system/node-red.service
[Unit]
Description=Node-RED
After=syslog.target network.target

This describes our service and indicates that it should be started after networking and syslog are functioning.

/etc/systemd/system/node-red.service
[Service]
ExecStart=/usr/local/bin/node-red-pi --max-old-space-size=128 -v
Restart=on-failure
KillSignal=SIGINT

ExecStart is the command needed to start our service. We call node-red-pi instead of plain node-red so we can pass some memory-saving options to Node.js. This should allow it to run well on any reasonably sized server, depending of course on how many flows you create in Node-RED (and how complicated they are). Restart=on-failure means systemd will try to restart Node-RED if it crashes, and KillSignal tells systemd the best way to quit Node-RED when it needs to shut down or restart the process.

/etc/systemd/system/node-red.service
# log output to syslog as 'node-red'
SyslogIdentifier=node-red
StandardOutput=syslog

This sets the label used when logging, and logs all output to the syslog service.

/etc/systemd/system/node-red.service
# non-root user to run as
WorkingDirectory=/home/sammy/
User=sammy
Group=sammy

We want to run Node-RED as our non-root user. The lines above tell systemd to launch Node-RED using our user and group, and from within our home directory.

/etc/systemd/system/node-red.service
[Install]
WantedBy=multi-user.target

WantedBy indicates the targets our service should run under. In this case, when Ubuntu boots into multi-user mode, it will know to also launch our Node-RED service. Muti-user mode is the default startup target.

Now that our service file is installed and understood, we need to enable it. This will enable it to execute on startup.

  1. sudo systemctl enable node-red

Let’s manually start the service now to test that it’s still working.

  1. sudo systemctl start node-red

Point a browser back at the server’s port 1880 and verify that Node-RED is back up. If it is, shut it back down until we secure the install in the next step.

  1. sudo systemctl stop node-red

Step 4 — Setting Up Nginx

We’re going to use Nginx to proxy the Node-RED service. This means Nginx will handle all of the SSL connections on port 443 (using the Let’s Encrypt certificates you previously set up), and then pass the traffic along to Node-RED.

Oopen a new Nginx configuration for the site.

  1. sudo nano /etc/nginx/sites-enabled/node-red.example.com

Copy and paste the following, changing the server name and certificate paths:

/etc/nginx/sites-enabled/node-red.example.com
server {
    listen 80;
    listen 443 ssl http2;
    server_name node-red.example.com;
    ssl_certificate /etc/letsencrypt/live/node-red.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/node-red.example.com/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers On;
    ssl_session_cache shared:SSL:128m;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;

    location / {
        if ($scheme = http) {
            return 301 https://$server_name$request_uri;
        }
        proxy_pass http://localhost:1880;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location '/.well-known/acme-challenge' {
        root /var/www/html;
    }
}

Save and close the file. Let’s explain what this file does.

The first three lines tell Nginx what ports to listen on, and what domain name to respond to. The ssl_certificate and ssl_certificate_key lines point to the certificates we retrieved from Let’s Encrypt. The remaining ssl_ lines choose protocols, ciphers, and options that are more secure than the defaults.

location / starts the block where we actually define our Node-RED proxy.

/etc/nginx/sites-enabled/node-red.example.com
if ($scheme = http) {
    return 301 https://$server_name$request_uri;
}

This block will match any plain, non-secure http connections, and redirect them to the https version of the site.

/etc/nginx/sites-enabled/node-red.example.com
proxy_pass http://localhost:1880;

We point to our Node-RED service here. It is available on localhost, at port 1880, so we pass connections to it there. The remainder of this block of configuration sets some headers that are important for proper proxy functioning. The Upgrade and Connection headers are especially important for handling Node-RED’s websocket connections.

Finally, we have a block to make sure the Let’s Encrypt challenge responses continue to be fetched from Nginx’s default web root:

/etc/nginx/sites-enabled/node-red.example.com
location '/.well-known/acme-challenge' {
    root /var/www/html;
}

Reload Nginx to pick up the new configuration.

  1. sudo systemctl reload nginx

Finally, start Node-RED again.

  1. sudo systemctl start node-red

Once again, navigate to your server: http://node-red.example.com. You should be redirected to https://node-red.example.com (note the https) and see the Node-RED admin interface. This means we’re now proxying Node-RED through Nginx. We just have a few more tweaks to lock down Node-RED, and then we’ll be finished.

Step 5 — Securing Node-RED and Wrapping Up

Now that our connection is secure, let’s add a password to the Node-RED admin. Instead of putting a bare password right into our settings file, we first make a one-way cryptographic hash of it, and use that instead. We’ll use node-red-admin to create the hash:

  1. node-red-admin hash-pw

You will be prompted for a password. Type it in, press ENTER, and a hash will be printed on screen. Copy that to your clipboard and open the Node-RED settings file.

  1. nano ~/.node-red/settings.js

Scroll down and uncomment the adminAuth block (by removing the "// " in front of each line). Change username to whatever you like, and paste the hash into the password field.

settings.js
adminAuth: {
    type: "credentials",
    users: [{
        username: "admin",
        password: "$2a$08$Ab9prIr1M8a5a1/Zx8.B9.uIOCPe.v90ZGuZc2kAATp6BHJ/WV5KS",
        permissions: "*"
    }]
},

While we’ve got the file open, uncomment the uihost line as well by removing the // at the front of the line.

settings.js
uiHost: "127.0.0.1",

This means Node-RED will only listen on the local interface, and wont be reachable directly by the outside world (it will only be accessed through the Nginx proxy). You can now save and close the file.

Update the firewall one last time, just to make sure Node-RED is never directly accessible.

  1. sudo ufw deny 1880

Finally, restart Node-RED.

  1. sudo systemctl restart node-red

Navigate to https://node-red.example.com and you’ll see a login screen instead of the main editing interface.

Node-RED's login screen

If your site is showing a login screen and an https connection, you’ve set everything up correctly.

Conclusion

We now have a reasonably secure installation of Node-RED, being proxied by Nginx using Let’s Encrypt for its SSL certificates. Log in and get wiring! There is much more information and project inspiration available at Node-RED’s website.

If you’ve enjoyed this tutorial and our broader community, consider checking out our DigitalOcean products which can also help you achieve your development goals.

Learn more here


About the authors
Default avatar
Developer and author at DigitalOcean.

Default avatar
senior technical writer

hi! i write do.co/docs now, but i used to be the senior tech editor publishing tutorials here in the community.


Still looking for an answer?

Was this helpful?
10 Comments

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

hello I have an error after step 4

sudo systemctl reload nginx Job for nginx.service failed. See “systemctl status nginx.service” and “journalctl -xeu nginx.service” for details.

for server_name node-red.example.com;

I use my ip address http://188.166.24.xx however it had been well on the way

"Welcome to nginx! If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org. Commercial support is available at nginx.com.

Thank you for using nginx."

These guides are excellent. I had a booboo where I was logged in as my root user through the whole installation rather than “sammy” with sudo rights. When it came to the step 5 I was editing the wrong settings.js file. Unless I missed a step - its not clear to login as that “sammy” user".

Also these guides would be SUPER Excellent if you had some fields at the beginning where you could enter your own variables like domain name and username then each steps code would update with your data so the text you copy is pre populated with exact data to paste. In my ubunutu when you paste the command it executes as well so it’d be good if it executed the correct code. :)

Hi, All has gone well except I cannot seem to get the Authentication to enable. There is some chatter on other support forums that you need to edit the correct settings.js file. I have installed the above while logged in as UserA lets say, so does the command;

nano ~/.node-red/settings.js

Automagically take me to the correct file?

I’ve checked my file umpteenth times and am almost sure its all correct. Can I view some logs or something to see where the issue could be?

I followed through this setup on Ubuntu 18.04 without issue (maybe?) until the final step where I am setting authentication. I can’t seem to get the authentication to appear. I found this page, with a solution, but I don’t quite follow, as I copied and pasted all commands, sudo or not.

Any tips?

Installed it all with no errors. When launching Node-Red it states that

18 Oct 17:35:21 - [info]

Welcome to Node-RED
===================

18 Oct 17:35:21 - [info] Node-RED version: v0.19.4
18 Oct 17:35:21 - [info] Node.js  version: v9.11.2
18 Oct 17:35:21 - [info] Linux 4.9.0-7-amd64 x64 LE
18 Oct 17:35:21 - [info] Loading palette nodes
18 Oct 17:35:21 - [warn] rpi-gpio : Raspberry Pi specific node set inactive
18 Oct 17:35:21 - [warn] rpi-gpio : Cannot find Pi RPi.GPIO python library
18 Oct 17:35:22 - [info] Settings file  : /root/.node-red/settings.js
18 Oct 17:35:22 - [info] Context store  : 'default' [module=memory]
18 Oct 17:35:22 - [info] User directory : /root/.node-red
18 Oct 17:35:22 - [warn] Projects disabled : editorTheme.projects.enabled=false
18 Oct 17:35:22 - [info] Flows file     : /root/.node-red/flows_project.json
18 Oct 17:35:22 - [info] Creating new flow file
18 Oct 17:35:22 - [warn]

---------------------------------------------------------------------
Your flow credentials file is encrypted using a system-generated key.

If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.

You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.
---------------------------------------------------------------------

18 Oct 17:35:22 - [info] Starting flows
18 Oct 17:35:22 - [info] Started flows
18 Oct 17:35:22 - [info] Server now running at http://127.0.0.1:1880/

How do I move the installation from localhost to my server’s IP or hosted domain?

I ran into a small problem when asked to initially test by going to the fully qualified host and domain name and port 1880.

I was installing via ssh of course and of course nginx was not set up to listen on that port so it failed. I just skipped down and finished the nginx configs and everything else worked exactly as detailed above.

Thank you for the great tutorial!

Thanks for this tutorial, i followed it and successfully set up a node-red server. However, in the node-red.service file, i had to use the line

ExecStart=/usr/bin/node-red-pi --max-old-space-size=128 -v

instead of

ExecStart=/usr/local/bin/node-red-pi --max-old-space-size=128 -v

The instructions to launch Node-RED on startup failed in my case. Node-RED was not installed to /usr/local/bin/node-red-pi as stated node-red.service file. To obtain the directory where Node-RED is installed use $which node-red. Secondly, the command node-red-pi specifically relates to devices with constrained memory like the Raspberry Pi and BeagleBone.

The instructions here have been a great help in my case.

After I run step 4, nginx stops loading.

-- Unit nginx.service has begun starting up.
Feb 25 00:46:57 nodered nginx[753]: nginx: [emerg] the size 134217728 of shared memory zone "SSL" conflicts with already declared size 10485760 in /etc/nginx/sites-enabled/XXXXX.XXXXX.com:10
Feb 25 00:46:57 nodered nginx[753]: nginx: configuration file /etc/nginx/nginx.conf test failed
Feb 25 00:46:57 nodered systemd[1]: nginx.service: Control process exited, code=exited status=1
Feb 25 00:46:57 nodered systemd[1]: Failed to start A high performance web server and a reverse proxy server.

Please help

Great tutorial! Thank You.

Only one issue… Node-RED is rejecting my login attempts. After a bit of investigation, if I unblock the 1880 port and connect via http and not https I can login perfectly. It seems that when I try connecting on https Node-Red is unable to issue a token.

Browser output excerpt:

  1. Request URL: https://example.com/settings?_=1485942900514
  2. Request Method: GET
  3. Status Code: 401 I have been unsuccessful in resolving this. Your help is appreciated.

Thanks