# Node-red server with nginx reverse proxy howto guide

**URL:** https://discourse.nodered.org/t/node-red-server-with-nginx-reverse-proxy-howto-guide/27397
**Category:** FAQs
**Created:** [27 May 2020 23:28 UTC](https://discourse.nodered.org/t/node-red-server-with-nginx-reverse-proxy-howto-guide/27397 "2020-05-27T23:28:07Z")
**Posts on this page:** 1
**Showing post:** 1

<div class="post-metadata">

### Author: ![meeki007](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/meeki007/32/12499_2.png) [@meeki007](https://discourse.nodered.org/u/meeki007)
#### Post date: [27 May 2020 23:28 UTC](https://discourse.nodered.org/t/node-red-server-with-nginx-reverse-proxy-howto-guide/27397/1 "2020-05-27T23:28:07Z")

</div>

Navigatable version on github  
[https://github.com/meeki007/node-red-server-howto-guide/blob/master/README.md](https://github.com/meeki007/node-red-server-howto-guide/blob/master/README.md)

## Ubuntu 20.04 - nigix - https - ssl - security - Fail2ban 403 bans, etc

## Table of Contents

- [Introduction](#Introduction)
- [Setup\_Server](#Setup_Server)
  - [Creating\_a\_new\_privileged\_user\_account](#Creating_a_new_privileged_user_account)
  - [Update\_Server](#Update_Server)
  - [Enable\_a\_firewall](#Enable_a_firewall)
  - [Install\_Fail2ban](#Install_Fail2ban)

- [Node-red](#Node-red)
  - [build-essential](#build-essential)
  - [nod-red\_script](#nod-red_script)
  - [Autostart\_on\_boot](#Autostart_on_boot)

- [Hosting\_to\_the\_world](#Hosting_to_the_world)
  - [Install\_Nginx](#Install_Nginx)
  - [DNS](#DNS)
  - [Reverse\_proxy](#Reverse_proxy)
  - [HTTPS\_SSL\_certbot](#HTTPS_SSL_certbot)

- [Security](#Security)
  - [adminAuth\_user\_password](#HTTPS_SSL_certbot)
  - [fail2ban\_403\_protection](#fail2ban_403_protection)

- [Extras](#Extras)  
\* [automatic\_increasing\_ban\_times](#automatic_increasing_ban_times)

## Introduction

This Guide is for setting up a **secure** Dedicated Server.  
  
  
Running node-red  
  
  
This guide assumes you have a running server with Ubuntu 20.04 and that you have access to terminal on the server. You can host this yourself however this guide does not address port forwarding from routers or DMZ settings and or ipv6 settings.

You need a Domain Name and the ability to point it to your IP address. Let’s Encrypt doesn’t issue certificates for bare IP addresses, only domain names. You’ll need to register a domain name in order to get a Let’s Encrypt certificate.

What your server needs: a visable IP address to the internet to include if you wish a ipv6 address.

I used a VPS (Virtual Private Server) provider. For less than $10 a month, I have a server, and I have complete root access to and can spin up Ubuntu on. I used [https://servercheap.net/pricing.php](https://servercheap.net/pricing.php) I was not paid or compensated to link them. Its just what I use.  
  
  
I suggest you purchase a server close to your geographical location.  
  
  
  
  
If all you are going to use this server for is node-red you will only need 1gb of ram and 1 cpu however I recommend 2gb of ram and 2 cpu's  
  
  
  
  
MORE! ram and cpu if you plan on running Huge flows with multiple/constantly running injections  
  
  
  
  
This Guide is **not** for individuals who fear the CLI (command line interface). If you have issues your going to need to read and search. You can always open an issue here [https://github.com/meeki007/node-red-server-howto-guide/issues](https://github.com/meeki007/node-red-server-howto-guide/issues) and if i have time I can try to help.

## Setup\_Server

Bring up a terminal on the server

##### Creating\_a\_new\_privileged\_user\_account

You should never log into your server as root. example ssh root@youripaddress  
If you have not or no privileged user account exists lets create one.  
  
  
If you have a privileged user account you can skip this step  
  
  
  
  
In terminal:

```auto
$ adduser YourChosenNameHere

```

  

Give your new user account sudo rights by appending (-a) the sudo group (-G) to the user’s group membership:  
  
  
  
  
In terminal:

```auto
$ usermod -a -G sudo YourChosenNameHere

```

  
Exit root account and login with the new privileged user account you have created  
  

##### Update\_Server

Update the local repositories and upgrade the operating system and installed applications by applying the latest patches.  
  
  
Keep settings or files during the upgrade if asked. Follow the suggestions presented in terminal  
  
  
  
  
In terminal:

```auto
$ sudo apt update && sudo apt upgrade -y

```

  
  

##### Enable\_a\_firewall

If you have a firewall setup you can skip this step.  
  
  
  
  
Install a firewall, enable it, and configure it only to allow network traffic that you designate  
  
  
  
  
In terminal:

```auto
$ sudo apt install ufw

```

  

UFW (universal firewall) denies all incoming connections and allows all outgoing connections  
  
  
Enable access to SSH, HTTP, and HTTPS  
  
  
  
  
In terminal:

```auto
$ sudo ufw allow ssh

```

```auto
$ sudo ufw allow http

```

```auto
$ sudo ufw allow https

```

  

Now lets start UFW  
  
  
  
  
In terminal:

```auto
$ sudo ufw enable

```

  

You can see what services are allowed and denied with:  
  
  
  
  
In terminal:

```auto
$ sudo ufw status

```

  

If you ever want to disable UFW, you can do so by typing:  
  
  
  
  
In terminal:

```auto
$ sudo ufw disable

```

  
  

##### Install\_Fail2ban

Fail2ban is an application that examines server logs looking for repeated or automated attacks. If any are found, it will alter the firewall to block the attacker’s IP address either permanently or for a specified amount of time.  
  
  
  
  
In terminal:

```auto
$ sudo apt install fail2ban -y

```

  

Copy the included configuration file  
  
  
  
  
In terminal:

```auto
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

```

  

And restart Fail2ban  
  
  
  
  
In terminal:

```auto
$ sudo service fail2ban restart

```

  
  

## Node-red

Install follows the guide @ [https://nodered.org/docs/getting-started/raspberrypi](https://nodered.org/docs/getting-started/raspberrypi)  
  
  
Using the install script method works for Ubuntu

##### build-essential

Install possible dependency build-essential first  
  
  
  
  
In terminal:

```auto
$ sudo apt install build-essential git

```

  
  

##### nod-red\_script

Install nod-red and its dependencies  
  
  
  
  
In terminal:

```auto
$ bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)

```

  
  

##### Autostart\_on\_boot
  
We want node-red to run automatically every time the server restarts  
  
In terminal:

```auto
$ sudo systemctl enable nodered.service

```

  
  

## Hosting\_to\_the\_world

We need to setup our DNS for our domain. Install Nginx to reverse proxy so users don't have to enter a port to get to the server. Install Lets encrypt certbot to issue ssl certificates and automate the process so you never have to manually renew ssl certificates; also so users can access the site using https for security and so browsers will not complain and block access. Configure fail2ban so random people on the internet can't mess with your server.

##### Install\_Nginx

Nginx is a web server which can also be used as a reverse proxy.  
  
  
By default, Nginx is configured to start automatically when the server boots/reboots

In terminal:

```auto
$ sudo apt install nginx

```

Check to see if Nginx is running

In terminal:

```auto
$ systemctl status nginx

```

Check to see if Nginx is hosting properly.  
  
  
In a web browser type your servers ip address with no port. IE http://server\_ip  
  
  
You should see a welcome to nginx page

##### DNS

You need to tie your server ipv4 and if you have one ipv6 addresses to you DNS records.  
I like to use subdomains for my reverse proxy needs in Nginx.  
  
  
  
  
Log into your domain name hosting provider of choice and add some records.  
  
  
  
  
DNS advice is outside the scope of this tutorial. You will need to learn and or ask your provider for help if you do not understand the steps below.  
  
  
  
  
Create an A record for your ipv4 server address.  
  
  
Create an AAAA record for your ipv6 server address.  
  
  
Now Create a CNAME record pointing a subdomain to your domain name. IE your\_domain\_name.com  
  
  
  
  
It should look somting like this:

| Hostname | Type | Address / Value |
| --- | --- | --- |
| | A | server\_ipv4\_address |
| | AAAA | server\_ipv6\_address |
| www | CNAME | your\_domain\_name.com |
| node-red | CNAME | your\_domain\_name.com |

The goal of all this is to create the address node-red.your\_domain\_name.com for users to access  
  
  
You can pick a subdomain name of your choice.

Testing that your domain works with Nginx. Enter your domain name. http://your\_domain\_name.com

You should see a welcome to nginx page

If not DO NOT PASS GO. Fix your domain issues.

##### Reverse\_proxy

This is used so when users goto node-red.your\_domain\_name.com they are directed to the node-red server running on port :1880

First create a server block file for the url , making sure to change:  
  
  
**server\_name node-red.your\_domain\_name.com;**  
  
  
To the [subdomain.domain.com](http://subdomain.domain.com) that you own

In terminal:

```auto
$ sudo nano /etc/nginx/sites-available/node-red.your_domain_name.com

```

This will open a text editor

Paste the following into the editor, making sure to change one line:  
  
  
**server\_name node-red.your\_domain\_name.com;**  
  
  
To the [subdomain.domain.com](http://subdomain.domain.com) that you own

```auto
#proxy for node-red @ port :1880
server {
    	listen 80;
	listen [::]:80;

    	server_name node-red.your_domain_name.com;

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

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

		#These header fields are required if your application is using Websockets    
		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;

    	}
}

```

Now enable the file by creating a link from it to the sites-enabled directory, which Nginx reads from during startup:  
  
  
making sure to change:  
  
  
**server\_name node-red.your\_domain\_name.com;**  
  
  
To the [subdomain.domain.com](http://subdomain.domain.com) that you own

In terminal:

```auto
$ sudo ln -s /etc/nginx/sites-available/node-red.your_domain_name.com /etc/nginx/sites-enabled/

```

To avoid a possible hash bucket memory problem that can arise from adding additional server names, it is necessary to adjust a single value in the /etc/nginx/nginx.conf file. Open the file:

In terminal:

```auto
$ sudo nano /etc/nginx/nginx.conf

```

Now uncomment (remove the # symbol) from the http section line **server\_names\_hash\_bucket\_size 64;** so it looks like this:

```auto
http {
    ...ignore stuff here...
    server_names_hash_bucket_size 64;
    ...ignore stuff here...
}

```

Next, test to make sure that there are no syntax errors in any of your Nginx files:

In terminal:

```auto
$ sudo nginx -t

```

Restart Nginx to enable your changes:

In terminal:

```auto
$ sudo systemctl restart nginx

```

**Later** if we ever need to disable a server block file simply remove the symbolic link.

In terminal:

```auto
$ sudo rm /etc/nginx/sites-enabled/node-red.your_domain_name.com

```

And don't forget to restart to effect changes

In terminal:

```auto
$ sudo systemctl restart nginx

```

Test if the reverse proxy is working  
  
  
Goto your website, non https, and make sure it works  
  
  
http://node-red.your\_domain\_name.com

The node-red page should load. I know its tempting but do not configure it now. exit the page / close the browser.

##### HTTPS\_SSL\_certbot

Install certbot to get ssl certificates for domain  
  
  
at this time cerbot not relesed for ppa package use snap

In terminal:

```auto
$ sudo snap install --beta certbot --classic

```

  
  
Generate the certificate for domain  
making sure to change:  
**server\_name node-red.your\_domain\_name.com;**  
To the subdomain.domain.com that you own

In terminal:

```auto
$ sudo certbot --nginx -d node-red.your_domain_name.com

```

If asked to redirect HTTP traffic to HTTPS, removing HTTP access:  
  
  
Select 2: Redirect - Make all requests redirect to secure HTTPS access.

Test if https is working  
  
  
Goto your website, https, and make sure it works  
  
  
https://node-red.your\_domain\_name.com

The node-red page should load. I know its tempting but do not configure it now. exit the page / close the browser.

Test that lets encrypt cerbot is working and will automatically update certificates before they expire

In terminal:

```auto
$ sudo certbot renew --dry-run

```

  
  

## Security

Setup node-reds built in login a password for the admin area, also create a fail2ban filter for 4xx failed requests.

##### adminAuth\_user\_password

First lets hash a password so we can add it to the settings.js file.

My method of choice for this is to use bcryptjs  
  
  
Add to your node-red manage pallet node-red-contrib-bcrypt  
  
  
  
  
Now import this flow into node-red

```auto
[{"id":"6fb8f86c.3dd218","type":"comment","z":"93ccda7b.0f6118","name":"create a key for a password","info":"","x":220,"y":120,"wires":[]},{"id":"2c990cc6.7e76e4","type":"bcrypt","z":"93ccda7b.0f6118","name":"","action":"encrypt","field":"payload","hash":"payload","rounds":"10","x":570,"y":160,"wires":[["480852c7.37515c"]]},{"id":"e203ec3d.eb8938","type":"inject","z":"93ccda7b.0f6118","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":160,"wires":[["15919cce.3e10a3"]]},{"id":"15919cce.3e10a3","type":"change","z":"93ccda7b.0f6118","name":"Enter Password Here","rules":[{"t":"set","p":"payload","pt":"msg","to":"MyPassword","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":160,"wires":[["2c990cc6.7e76e4"]]},{"id":"480852c7.37515c","type":"debug","z":"93ccda7b.0f6118","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":730,"y":160,"wires":[]}]

```

Replace MyPassword with your password!!!  
  
  
Trigger the flow and check the msg.payload  
  
  
copy the payload as it is your password hash you will need next  
  
  
  
  
We need to setup a user name and password by editing node-red's settings.js file.  
  
  
Edit the settings.js file in our current privileged\_user\_account /home/YourChosenNameHere/.node-red/settings.js  
  
  
We can use $HOME variable to accomplish this  
  
  
  
  
In terminal:

```auto
$ nano $HOME/.node-red/settings.js

```

This will open a text editor

Edit the adminAuth section removing forward slashes // so it looks like this:

```auto
adminAuth: {
    type: "credentials",
    users: [
        {
            username: "admin",
            password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.",
            permissions: "*"
        }
    ]
}

```

  
  
Replace $2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN. within QUOTES with your password hash you created.  
  

More information on this can be found at: [https://nodered.org/docs/user-guide/runtime/securing-node-red](https://nodered.org/docs/user-guide/runtime/securing-node-red)

##### fail2ban\_403\_protection

Every time a user....hacker...etc tries to login to node-red with a bad user name or password it sends a 403 Forbidden error  
  
  
This response code indicates that the server understood the request but refuses to authorize it  
  
  
  
  
What we would like todo is ban users who have multiple failed attempts to login  
  
  
That way we can keep the bad people from password spamming the server trying to gain access.  
  
  
  
  
Lets block 404, 444, 403, 400 responses from the server. Feel free to read up on these codes but the gist of it is we will be blocking people trying to gain access to areas they should not be trying to get into.  
  
  
  
  
  
  
Create a new fail2ban filter for 404, 444, 403, 400 responses from the server.

In terminal:

```auto
sudo nano /etc/fail2ban/filter.d/nginx-4xx.conf

```

This will open a text editor

Add the following to the file:

```auto
[Definition]
failregex = ^<HOST>.*"(GET|POST).*" (404|444|403|400) .*$
ignoreregex =

```

Now, edit your /etc/fail2ban/jail.conf, to use the new filter we created and ban after 10 failed attempts.

In terminal:

```auto
$ sudo nano /etc/fail2ban/jail.conf

```

This will open a text editor

Add the following to the bottom of the file:

```auto
[nginx-4xx]
enabled = true
port = http,https
logpath = %(nginx_access_log)s
maxretry = 10

```

Restart fail2ban

In terminal:

```auto
$ sudo service fail2ban restart

```

Check that the new rule is working

In terminal:

```auto
sudo fail2ban-client status nginx-4xx

```

Now the user will be banned for the amount of time you have set in fail2ban after 10 failed attempts

you can check this is working with the logs.

In terminal:

```auto
$ sudo cat /var/log/fail2ban.log | grep Ban

```

and to check in on what the nginx log is producing

In terminal:

```auto
$ sudo cat /var/log/nginx/access.log

```

## Extras

##### automatic\_increasing\_ban\_times

Many malicious actors will just take note of the fixed ban time and just keep at it every 10min. Instead of increasing the fixed time we want to increase the time for specific bad actors and not every one.

In terminal:

```auto
$ sudo nano /etc/fail2ban/jail.conf

```

This will open a text editor

search for and remove the # sign in front of the following lines so they look like this:

```auto
bantime.increment = true

bantime.factor = 1

bantime.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFact>

```

Restart fail2ban

In terminal:

```auto
$ sudo service fail2ban restart

```

**END OF TUTORIAL**

---

_[View the full topic](https://discourse.nodered.org/t/node-red-server-with-nginx-reverse-proxy-howto-guide/27397)._
