Node-RED SSL using Letsencrypt & Certbot

@Paul-Reed Thank you for this post! it is great what have you done here. By the way I ask here for some helps. The explained configuration with apache goes straight but now I cannot access my node-red anymore. I'm getting this error in the browser.

# Proxy Error

The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request

Reason:  **Error reading from remote server**

Apache/2.4.38 (Raspbian) Server at 192.168.0.38 Port 80

For sure is a config apache server problem. Anyone can explain what is wrong ?

Sorry I've not installed apache, so can't really help further with apache related errors.
Hopefully other members will be more familiar with apache, and be better placed to assist.
This guide was really intended for non-apache users for that reason.

Hi guys,

I would need a bit a help from you. I am having a Raspberry with node-red which is accessible through VPS. RPi starts automatically at boot a ssh reverse tunnel to a VPS and then I can reach RPi through VPS. Port 80 of the VPS is forwarded to port 1880 on RPi. On VPS I'm having a domain configured, so I can access node-red on RPi when I'm opening a page to http://domain.com.
My question would be - if I would like to use SSL, where should I install the certificates, on VPS or on RPi? What else should I configure? Have anyone from you implemented this? Thank you very much in advance.

Are you using Certbot & Letsencrypt?

Yes, I would like to use Certbot and Letsencrypt, but don't know whether I have to install it on RPi or VPS side.
What I did so far: installed Certbot on RPi and requested a certificate with command "certbot certonly --standalone", but this fails with error:
Domain: mydomain.com
Type: unauthorized
I assume this is because of the fact that mydomain.com is set on VPS and not on RPi.
Then I've installed certbot on VPS and requested a certificate with mydomain. This worked, I've got a certificate and key but don't know if this is right. If yes, don't know what to do next.
Thank you very much.

Hi Ioan,

I have no knowledge about certbot, but I'm about to announce a new LetsEncrypt node for Node-RED. So I have been playing with the acme protocol already, which hopefully can get you a bit started ...

  • When you request a new certificate for a domain (mydomain.com), the guys from Letsencrypt have to be sure that you are the owner of domain.com. Otherwise everybody could request a certificate, which means it wouldn't be secure anymore ...

    To make sure you are the owner, they will send a token to the acme client (in your case Certbot) and that client needs to make that token available on port 80 of the domain:

    image

    1. Certbot on your VPS sends a certificate request to Letsencrypt. Letsencrypt returns a token that Certbot needs to make available on port 80.
    2. Letsencrypt will try to get the token via port 80. If it succeeds, you will get your certificate.

    The reason they use port 80 (or 443) is that you need to be administrator (or root user) to listen to port 80 on any system. So only the administrator (who controls the server) has access to it. That way they know they are talking to someone that controls the domain. And that is also the reason that they don't allow redirects to other ports (to avoid cheating)!

    So I 'think' that if you should install certbot on your RPI, and you forward port 80 of your domain to port 80 of your RPI, then I assume it should also work...

  • Once you have received your Letsencrypt certificate, that certificate should be used by your webserver when you connect to Node-RED:

    image

    You navigate to your mydomain.com from your browser. Even when Node-RED is running on your RPI (and the certificate is stored into your key files there), it doesn't matter for your browser. Your browser receives a certificate, and inside the certificate the domain name is mydomain.com. Your browser sees that the domain inside the certificate matches the domain name you have entered in the browser's address bar, so the certificate is marked as valid ...

Good luck!
Bart

2 Likes

Hi Bart, the process you outline isn't the only one. You can also validate via DNS if your DNS provider supports the appropriate protocol (which Cloudflare and others do).

That is a much better process for home users as it means that you don't have to expose your home network to the Internet just to get certbot to work.

Some details here:

2 Likes

...as described in https://letsencrypt.org/docs/challenge-types/ it can be more difficult to implement as it's necessary to create a TXT record, and place it under the domain name.
There are also security concerns in the event of the web server being hacked.

Hi Julian,
Indeed I only have been discussing the "http-01" challenge. But suppose the RPI (running Node-RED and Certbot) isn't connected to the internet. How does certbot gets its certificates then?
On this link I found this sequence diagram:

image

E.g. not clear to me what the control server would look like. Could you please explain (in dummy language) what a home setup could look like to request Letsencrypt certificates for RPI's that are not exposed to the internet. Because it would be very nice if each internal device could have Letsencrypt certificates ...

Thanks !!!!!

Useful points of Note Paul. For me not a problem, the Cloudflare DNS is entirely separate to any web servers and separate to any other ISPs and has its own 2-factor auth. In addition, the updates run from a Pi that doesn't present at all to the Internet - indeed, that was the whole point of using the DNS method for me. If you have an Internet facing web server, then the http method will be simpler but is much more complex if not. Creating a TXT entry on a good DNS service like Cloudflare is trivial.

Well, it has to be connected to the Internet somehow or you can't interact with Let's Encrypt at all can you? :slight_smile:

With the http method, you have to expose a web server to the internet. With the DNS method, you don't. So for me, I've registered a spare domain and used the DNS method but the server that consumes the domain names is never reachable from the Internet. My router provides internal DNS routing which allows the certs to work.

To update the certs, a script runs that connects to Let's Encrypt from the registered domain - so LE see's the script's connection as coming from the registered domain and checks the DNS (Cloudflare) for the TXT record (rather than having to check a web server for it).

Hope that makes sense?

Well, I cheat - I registered a wild-card, multi-domain cert :slight_smile: Then I sync the cert files if I need to. The important thing is to ensure that the private key file is kept completely secure.

I will need to digest that next week :wink:
The RPI is not connected to the internet, then I don't understand how it's certificates can be updated... Or do you mean that your router requests the certificate from Letsencrypt, and passes them somehow to the RPI. Or does the RPI never get the certificate, and you keep the private keys/public keys somewhere else?
If you have some time, a quickly drawn sketch on a small piece of toilet paper perhaps would be sufficient to demystify this mechanism :roll_eyes:
Appreciate your feedback!

I think it's this comment which is causing the confusion;

I suspect that Julian was describing;

you don't have to expose your home network to the Internet by spinning up a webserver on Port 80

In all cases, an internet connection is necessary otherwise, as Julian has said;

The Pi can reach OUT to the internet but nothing can reach IN. So the script runs, contacts the LE servers to request an updated cert. LE checks DNS, approves the request and the updated cert comes in via the same connection. At no point can anything from the Internet connect to the Pi. Everything is driven from the Pi connecting to the LE server.

In other words, everything is PULLed by the Pi from the LE servers, never PUSHed from the Internet. This is much safer & requires no messing with your router, firewall or web server.

3 Likes

Great post. Many thanks.

Out of interest why do you copy the certificates to a different folder rather than just using them where they are generated?

Node-RED normally runs as a 'user', and Letsencrypt creates the certificates in etc/letsencrypt/live/ with root ownership, and therefore without changing the ownership of the certificates to pi, node_RED would not be able to read them.

So... rather than start altering files that sit within the Letsencrypt directory, I prefer to copy the certificates to the node-RED user directory and then use chown to make them readable (it's all done by the script).
That then keeps the two services independent, and for me has the advantage that when I back-up node-RED, it also backs up the node-RED certificates in the NR user dir. If I ever needed to quickly restore the backup, I could be back online, complete with https in minutes without having to worry about Letsencrypt/Certbot.

4 Likes

4 posts were split to a new topic: OpenSSL Certificate not working

Hi Paul,
thanks for sharing this usefull post!
Anyway I have a question for anyone who can clarify me the following.
I'm missing if (and when) the "renewal_success" script will be run in order to copy the new generated certificates.
In my understanding there was, in an earlier version, a cron job to do that. Now according to latest instructions the cron job is no longer needed (certbot setup by itself) thus I can't figure out who will call that script and when.
Thanks in advance.

I can't remember where all this started now. I can only give you my working setup and it has been rock-solid since I set it up in 2018.

I use the acme.sh shell script that runs on a CRON script as a user not root:

28 0 * * * "/home/home/.acme.sh"/acme.sh --cron --home "/home/home/.acme.sh" > /dev/null

I actually have 2 domains that I fetch certificates for, each cert having wildcard sub-domains specified so that I can use the certs for multiple uses (my needs aren't for too much security, if I were using this for internet facing services, I'd probably have separate certs for each service).

All of the resulting files are owned by the user that runs the CRON, not by root. That also isn't as secure and if I needed that security, I would run as root but then at the end of each run, have a script that changes ownership of the public key to allow it to be copied. But then you also have to allow the user running Node-RED and any other services to have read access to the private key or make copies of that as well. Can be done either way.

Because I'm running as the same user as NR and because I don't need lots of security, I simply point NR at the folder containing the certs/keys.

If you are copying things around, best to have separate certs for each use.

If you look at the first post in this thread, you'll see this section;

There we create a script which certbot will automatically run, IF new certificates have been created (as it's in the renewal-hooks directory). That script will copy across the certs to your node-RED directory.

Correct when installed on a Pi, as the Certbot installation will create it's own time schedule as part of the installation.

Hey guys,
Also don't forget that we spend quite some time at the time being on this pull-request, to have automatic certificate renewal into Node-RED 1.1.0 and above... Then Node-RED will detect and load the renewed certificates automatically, without having to restart Node-RED...
Bart

3 Likes