# Node-RED SSL using Letsencrypt & Certbot

**URL:** <https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606>\
**Category:** Share Your Projects\
**Tags:** security\
**Created:** [6 November 2019 20:22 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606 "2019-11-06T20:22:22Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [6 November 2019 20:22 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/1 "2019-11-06T20:22:22Z")

</div>

I've written this up in case it helps other who may wish to secure their node-RED online presence, by using SSL certificates.  
The installation uses Letsencrypt to issue the certificates and also Certbot to fully automate and handle renewals - so it's a fit & forget solution.

**Pre-requisites**  
I've started with a RPi3b+ and a fresh 'Buster' operating system, with node-RED installed via the official script.  
Because node-RED is going to provide my online presence, no other webserver (such as apache) has been installed. If you do intend to also run another webserver as well as node-RED, then the Certbot installation is slightly different and not covered here, but see [this tutorial](https://pimylifeup.com/raspberry-pi-ssl-lets-encrypt/) for the necessary changes.  
It's important at this stage that you have secured your node-RED editor by following [this guide](https://nodered.org/docs/user-guide/runtime/securing-node-red#usernamepassword-based-authentication), then ensure that port forwarding is setup in your router for ports 1880 & 80 (port 80 is required by certbot).  
You must also have a domain name, and which points to your server.  
Ensure that you can access your node-RED editor via your domain name ([http://mysite.com:1880](http://mysite.com:1880)) before going any further, otherwise Certbot will fail.

Create a folder to hold your new certs; `mkdir /home/pi/.node-red/certs`

**Install Certbot**  
Most of the following commands require root privilidge, so let's make life easier!  
`sudo su`

Install Certbot  
`apt-get install certbot`

Obtain a set of certificates  
`certbot certonly --standalone`  
This will take a few minutes and should ask you a number of questions, such as email address, domain name, etc (nothing complicated!!) during that process.

Lets now create a script to automatically move a copy of the certs to your `node-red/certs` folder, prepare them for use by node-RED, and restart node-RED so that the new certificate is applied.  
This script will only run if the certificate is successfully renewed.  
Create a script called **renewal\_success** in `/etc/letsencrypt/renewal-hooks/deploy/`

```auto
#!/bin/bash

domain=mydomain.com
node_dir=/home/pi/.node-red/certs
node_user=pi

cp /etc/letsencrypt/live/$domain/*.pem "$node_dir"/
chown $node_user "$node_dir"/*.pem

```

...and make executable;  
`chmod u+x /etc/letsencrypt/renewal-hooks/deploy/renewal_success`

Now run the script;  
`/etc/letsencrypt/renewal-hooks/deploy/./renewal_success`  
and you should find that you will now have 4 certs in your node-red/certs folder, and node-RED restarted.

The Pi installation package automatically creates a systemd timer that runs twice daily (at randomised times) to check if it is necessary to renew the certificates, and although Letsencrypt certificates have a life of 90 days, they will be renewed 30 days before expiry.  
To change the timing of the renewal checks, or disable them completely, see [this post](https://community.letsencrypt.org/t/cerbot-cron-job/23895/5).

So that concludes installing & setting up certbot, so now exit su privilege;  
`exit`

Add certificate links to the node-red settings file;

```auto
    https: {
    key: fs.readFileSync('/home/pi/.node-red/certs/privkey.pem'),
    cert: fs.readFileSync('/home/pi/.node-red/certs/fullchain.pem')
           },

```

To ensure that node-RED loads the new certificates when they have been renewed, enable `httpsRefreshInterval` in the settings file.

and enable this option to force http visitors to use https;  
`requireHttps: true,`

...then reboot node-red to restart your SSL enabled server;  
`node-red-restart`

Many thanks to @recursivecodes for writing the Oracle cloud tutorial on which this is based.

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [6 November 2019 20:27 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/2 "2019-11-06T20:27:37Z")

</div>

> [@Paul-Reed](#):
>
> add an entry to crontab, that runs every night at a random time between 2am & 3am

Hi Paul,  
Thanks for sharing this! Just what I was looking for... Can the crontab be replaced by e.g. the cron-plus node, to integrate it even more into Node-RED?

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [6 November 2019 20:36 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/3 "2019-11-06T20:36:57Z")

</div>

> [@BartButenaers](#):
>
> Can the crontab be replaced by e.g. the cron-plus node

Yes it could. You only need to run the command `certbot renew` (as root) to trigger the renew process.  
But note that node-RED will not read the new certificates until the NR server is restarted, and if you look at the cron entry, there's a post-hook in there that does exactly that, and furthermore only restarts node-RED **if a certificate renewal has been made** , otherwise it doesn't restart.

You can simulate an actual renewal to test by using `sudo certbot renew --dry-run` whilst tailing the log file; `sudo tail -f /var/log/letsencrypt/letsencrypt.log`

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [6 November 2019 21:29 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/4 "2019-11-06T21:29:49Z")

</div>

> [@Paul-Reed](#):
>
> restarts node-RED

Ah ok. Sorry had overlooked that you had to restart Node-RED. That is a pitty. I now see [here](https://github.com/nodejs/node/issues/4464) indeed that NodeJs needs this [pull-request](https://github.com/nodejs/node/pull/23644) to allow the credentials to be hot swapped, for new connections being created. Wasn't aware of that...

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [6 November 2019 21:43 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/5 "2019-11-06T21:43:19Z")

</div>

> [@BartButenaers](#):
>
> That is a pitty.

It's a quick restart just once every 2 months in the middle of the night! I can live with that 😉

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [9 November 2019 20:24 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/6 "2019-11-09T20:24:57Z")

</div>

I've just updated the first post above to use the `fullchain.pem` certificate instead of `cert.pem` on the advice of the Letsencrypt guys.

> [@Paul-Reed](#):
>
> ```
> https: {
> key: fs.readFileSync('/home/pi/.node-red/certs/privkey.pem'),
> cert: fs.readFileSync('/home/pi/.node-red/certs/fullchain.pem')
> },
> 
> ```

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [9 November 2019 21:39 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/7 "2019-11-09T21:39:06Z")

</div>

> [@Paul-Reed](#):
>
> It's a quick restart just once every 2 months in the middle of the night! I can live with that

Urm, that's odd, I don't do that. Hmm, what am I doing that is different I wonder? Surely I'm not restarting NR that often for other reasons?

Well I won't be able to find out until January.

---

<div class="post-metadata">

**Author:** ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)\
**Post date:** [9 November 2019 21:43 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/8 "2019-11-09T21:43:28Z")

</div>

Julian, do you have a paid account?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [9 November 2019 21:44 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/9 "2019-11-09T21:44:12Z")

</div>

No. The last change was in October.

It is possible that this year has seen me updating that system more than usual and so restarting it more often. It is even possible that I set up a CRON job and completely forgot about it 🤣

I'll get round to checking at some point.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [10 November 2019 21:45 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/10 "2019-11-10T21:45:45Z")

</div>

Just updated the first post above.

After checking the Letsencrypt log, I found that the renewal application was being made at times outside the range of the custom cron setting, and upon further checking it appears that the Pi installation package also sets up systemd to run the process twice daily at random times.  
See [this post](https://community.letsencrypt.org/t/cerbot-cron-job/23895/5).

So no need for the cron job - it has been removed, and the post-hook function has been now been moved to the shell script instead.

It appears that the configuration of Certbot varies dependent upon the OS.

@BartButenaers - for info

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [13 November 2019 09:39 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/11 "2019-11-13T09:39:52Z")

</div>

Hi Paul,

I am trying to do the same steps on my PI. For some reason I have jessie which does not include certbot. I found [this post](https://certbot.eff.org/lets-encrypt/debianjessie-apache.html) and installed certbot-auto. It does not have -d parameter, so I can only run as certonly --standalone. During this I get this:

```auto
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for ringlo.ddns.net
Cleaning up challenges
Problem binding to port 80: Could not bind to IPv4 or IPv6.

```

So this is the point when letsencrypt is trying to check that it is indeed my server, right? But how will it perform the challenge if nothing is running on port 80. Or do I need to set up apache for this?

I got a bit confused.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [13 November 2019 09:52 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/12 "2019-11-13T09:52:00Z")

</div>

> [@nygma2004](#):
>
> So this is the point when letsencrypt is trying to check that it is indeed my server, right?

Yes, correct.  
It appears from your link, that you've chosen the version of certbot intended to be run alongside an apache server. If you are also running Apache, then as I said in my first post -

> [@Paul-Reed](#):
>
> Because node-RED is going to provide my online presence, no other webserver (such as apache) has been installed. If you do intend to also run another webserver as well as node-RED, then the Certbot installation is slightly different and not covered here, but see [this tutorial](https://pimylifeup.com/raspberry-pi-ssl-lets-encrypt/) for the necessary changes.

From what I've read, if you don't have any other webserver, then use the Certbot version which spins up a python server to do the verification.  
If however you do have another server, then the verification needs to be run through that other webserver (apache).

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [13 November 2019 09:54 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/13 "2019-11-13T09:54:55Z")

</div>

OK, I understand now. So I need to find out how can I install the standalone certbot in jessie. As apt says "unable to locate package certbot".

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [13 November 2019 09:57 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/14 "2019-11-13T09:57:38Z")

</div>

> [@nygma2004](#):
>
> As apt says "unable to locate package certbot"

I haven't looked what is avaialble in Jessie, but have you tried updating your sources `sudo apt-get update` first.

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [13 November 2019 11:09 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/15 "2019-11-13T11:09:06Z")

</div>

I did `sudo apt-get update` but it did not help. What I did instead if fired up apache2 on port 80 (it is normally nor running), got the certificate created, copied it to the "cert" folder, changed the settings.js and restarted NR. Chrome is still saying that it is "not secure". When I view the certificate, it says `Issued to: ringlo.ddns.net` so that is definitely my certificate. When I look at the certification path I see Let's Encrypt Authority X3, and DST Root CA X3.  
So what is Chrome's problem with this certificate? It this about that the challange was on port 80 and now we are on port 1880?

And do I understand correctly, that with the process I used above the certificate renewal will not work unless the apache server is running?

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [13 November 2019 11:34 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/16 "2019-11-13T11:34:33Z")

</div>

> [@nygma2004](#):
>
> got the certificate created, copied it to the "cert" folder, changed the settings.js and restarted NR

Have you changed ownership of the certs, so node-RED can access them OK?  
It's included it the script in the first post.

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [13 November 2019 12:09 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/17 "2019-11-13T12:09:44Z")

</div>

yes, I did. In fact I ran the script after the certificate got generated and it copied the files to the folder under node-red. And since it says "issued to: [ringlo.ddns.net](http://ringlo.ddns.net)" I know it is using these certificates. Previously I had a self signed certificate which has no root CA.  
Do I just need to restart my computer for Chome to forget something?

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [13 November 2019 12:14 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/18 "2019-11-13T12:14:00Z")

</div>

As you probably have not added the certificates to Apache, can you stop apache and then look at just your node-RED server, as [http://ringlo.ddns.net/](http://ringlo.ddns.net/) seems to be pointing to 'Saia PCD Web Server'.  
Also anything in the node-RED log?

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [13 November 2019 12:21 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/19 "2019-11-13T12:21:28Z")

</div>

> [@Paul-Reed](#):
>
> [http://ringlo.ddns.net/](http://ringlo.ddns.net/)

Yes, and I would like to keep port 80 as it is, but you can reach Node red on [https://ringlo.ddns.net:1880/](https://ringlo.ddns.net:1880/)

---

<div class="post-metadata">

**Author:** ![nygma2004](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nygma2004/32/1308_2.png) [@nygma2004](https://discourse.nodered.org/u/nygma2004)\
**Post date:** [13 November 2019 12:23 UTC](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606/20 "2019-11-13T12:23:22Z")

</div>

@Paul-Reed: this is all my bad, I am so sorry. I opened my NR as [https://192.168.1.80:1880](https://192.168.1.80:1880) instead of using the domain. Of course Chrome has issues as the IP does not match the domain of the certificate. Such a rookie mistake. I am so sorry.

[Next page](https://discourse.nodered.org/t/node-red-ssl-using-letsencrypt-certbot/17606.md?page=2)
