Node-red is a helpful tool to let people without software development skills program their devices own their own. But if you want to run node-red on a machine with very limited data volume and data bandwith, like IoT devices, node-red seems to be the wrong solution. Node-red comes with an integrated HTTP server, providing all the editor etc itself. Just loading the node-red editor costs about 3MB of traffic – that doesn’t seem much, but is a fortune for low volume / bandwidth devices.

~3MB for loading the editor by accessing

So I tried to find a solution as easy and unintrusive as possible – as always….

I started 2 node-red instances (on 2 different machines to demonstrate that there are no shared ressources) and used Caddy server to proxy all static HTML, CSS and JavaScript related files to my local node-red instance. All RESTful stuff and WebSocket connections were proxied to the node-red instance on the other maschine and ..

.. that’s already it! It worked.

The size of requests for injectors, debuggers, HTTP requests and so on were of very small impact.

Left side: local instance; right side: remote instance
Static files are served by the local instance and requests to the API are procied to the remote instance (see “/flows” and “/inject”)

Here is the caddy config I used to get this all working. Run it on the same machine as the local node-red instance: {
  log / stdout
  # local:
  proxy /
  # remote:
  proxy /settings rpi-iot:1880
  proxy /user rpi-iot:1880
  proxy /library rpi-iot:1880
  proxy /context rpi-iot:1880
  proxy /nodes rpi-iot:1880
  proxy /inject rpi-iot:1880
  proxy /credentials rpi-iot:1880
  proxy /flows rpi-iot:1880
  proxy /debug rpi-iot:1880
  # remote, custom:
  proxy /api/ rpi-iot:1880
  # remote, WebSocket:
  proxy /comms rpi-iot:1880 {

I decided not to proxy path “/uisettings” to the remote instance as I want to have my settings applied to the editor, no matter which remote instance I want to proxy to. If you want to have different uisettings for every machine, proxy that path to the remote instance, too.

Plus I proxied an artificial path “/api” so that I can have HTTP endpoint nodes that are proxied to the remote instance. This requires the endpoint’s path always starting with “/api/”.

In order to have HTTP endpoint APIs, the artificial path “/api” was also proxied to the remot instance

But the best way to have your endpoints always have a path with a leading “/api” is to change your settings.js file for node-red and uncommenting “httpNodeRoot” and setting the path to “/api”.

Gladly, you are not limited by using Caddy server only, there are many other servers and proxies out there that can proxy paths to other machines. But it’s you job in fiding them. 🙂

But there is also bad news: This proxy method (at least with my Caddy config) is that you can only have one remote instance be proxied to. Because there is no context whatsoever on what remote instance to proxy to. As the path is just “”. You could use Caddy’s “rewrite” to add context, so the path could look like this: “” which proxies to “machine1”, but that’s on you to make. I would be interested in how you solved it.

Last but not least, to save unused ressources on your IoT device, deactivate the editor that otherwise would try to serve the static files which are already served by the server, thanks to all the “proxying”.

Disable the editor which just means to not serve static HTML, CSS, JS, etc. files

I hope this helps rolling out node-red on your IoT device. And if this helps, please comment on how you did it exactly, so we can learn from each other.