Skip to Content

What “Node-RED” means here, and which door you just opened

one name, four layers
Node-RED Guide · Part 1

What “Node-RED” means here, and which door you just opened

Click OPEN WEB UI in Home Assistant and you get an editor labeled Node-RED. That single word is quietly standing in for four separate pieces of software, each with its own version number, its own job, and its own way of breaking. This part pins all four, walks through the official install sequence for the Home Assistant Community App, and then does the part that actually matters once the editor is open: which door you came in through, and which of the doors behind it are still unlocked.

4
Layers hiding inside the word “Node-RED”: the Add-on (22.0.1), the Node-RED runtime (5.0.2), the HA WebSocket integration (0.80.3), and the optional Dashboard 2 (1.30.2)
2024.3+
The Home Assistant version HA WebSocket 0.80.3 actually needs. The Add-on manifest's own install threshold is only 2023.3.0 — meeting that number alone is not enough
3
Separate authentication checks bundled into one Add-on: the editor login, the http_node credentials guarding /endpoint/, and http_static. None of the three covers the other two
One name, four layers

“Node-RED” is doing the work of four separate names

This guide pins four versions and treats them as four different things, because they are: the Home Assistant Community App that installs and runs the container, the Node-RED runtime that draws the editor and executes your flows, the HA WebSocket node package that talks to Home Assistant, and an optional dashboard that most installs never add. Calling all of it “Node-RED 22” is how people end up checking the wrong version, applying a setting to the wrong layer, or assuming that one layer's login protects a door it has never heard of.

What you clickedOPEN WEB UI in Home Assistant, which opens the Node-RED editor — the piece that Node-RED 5.0.2 itself draws and runs.
What actually got you thereHome Assistant Community App: Node-RED 22.0.1 built the container, started the service, and routed you in over Ingress. It is a different program, with its own version number, and it is the one you check first when the app itself fails to start.
In plain terms

It is the difference between a building, its elevator, and the badge reader on one office door. The Add-on is the building and the front door — it decides who gets let onto the property at all. Node-RED is the elevator that actually moves you between floors once you are inside. HA WebSocket is the badge reader on the Home Assistant office's door, on one specific floor. Reporting “the elevator is broken” when the real problem is that the front door never opened is how an evening disappears.

The examples later in this guide build toward real automations — a hallway light such as light.living_room turning on when someone passes a motion sensor, a reminder sent when everyone leaves, a temperature check that fires a notification. The very first flow you build, in the next part, controls nothing. It produces a message and a line in Debug, and that is deliberate: you learn the runtime before you let it touch a device.

Terminology, and it stays in English throughout this guide: a flow is an automation made of nodes and wires; a node receives, processes, or sends data; a wire decides where a message goes next; a message (msg) is the object that carries data between nodes; the runtime is what actually executes a deployed flow.
The four pinned versions

Four layers, four version numbers, and only one of them is optional

Every claim in this guide is checked against one specific commit of each project, not against whatever the main branch happens to look like today. That is what “pinned” means here, and it is why a screen that looks different on your install is worth a version check before it is worth a bug report.

LayerPinned versionResponsibilitiesLimits
Home Assistant Community App: Node-RED22.0.1Container image, Supervisor manifest, Ingress, data mounts, startup options, preinstalled packagesThis is not the Node-RED runtime version
Node-RED5.0.2Browser editor, runtime, message model, Deploy, core nodesScreens and behavior from other patch versions are not guaranteed to match
node-red-contrib-home-assistant-websocket0.80.3Home Assistant server config, events, state queries, the Action node, companion entity nodesThis is not Home Assistant Core
FlowFuse Dashboard 21.30.2, optionalDashboard configuration and widget nodes, after a separate installNot an Add-on dependency. Do not describe it as built in
flowchart TD
  A["Add-on 22.0.1
packages, Ingress, mounts, startup"] --> B["Node-RED 5.0.2
editor, runtime, Deploy, core nodes"] B --> C["HA WebSocket 0.80.3
server connection, events, Action node"] B -.-> D["FlowFuse Dashboard 2 1.30.2
optional, installed separately"]
One solid chain, one dotted branchThree boxes are joined by solid arrows — Add-on, runtime, and HA WebSocket are all present the moment you finish the official install. The dashboard box hangs off the runtime on a dotted line, which is the one arrow in this picture that is not there until you add it yourself.

The Add-on's pinned node-red/package.json lists exact dependencies, and what is on that list matters as much as what is not:

node-red — 5.0.2
node-red-contrib-home-assistant-websocket — 0.80.3
@node-red-contrib-themes theme collection — 5.0.1
@flowfuse/node-red-dashboard — not listed at all

“Dashboard 2” in the package name identifies a product generation, not an instruction to pin some unrelated npm major version to 2. It is simply the name FlowFuse gives the current dashboard line.

Thresholds and who does what

Two thresholds that look like one, and who does what when a light should turn on

The Add-on manifest declares homeassistant: 2023.3.0. That is the number the Supervisor checks before it lets you install the Add-on at all — it is not the complete compatibility story. HA WebSocket 0.80.3's own README lists a separate, higher bar: Home Assistant 2024.3+, Node-RED 3.1.1+, and Node.js 18.2.0+. The bundled Node-RED 5.0.2 already clears its minimum, so the number worth holding onto is the Home Assistant one.

Version or valueSource and purposeCorrect interpretation
2023.3.0Add-on manifest homeassistantSupervisor installation threshold only
2024.3+HA WebSocket 0.80.3 READMEThe Home Assistant prerequisite for this integration package
3.1.1+HA WebSocket READMEPackage minimum for Node-RED — not this guide's actual baseline of 5.0.2
18.2.0+HA WebSocket READMEPackage minimum for Node.js. The Add-on manages Node.js through its own image
aarch64, amd64Add-on manifest archThe two architectures 22.0.1 declares. The manifest also sets init: false

init: false is a container-manifest flag, not safe_mode. Do not fold the manifest's own install threshold, a README's user-facing prerequisite, and a container flag into one imagined “minimum Home Assistant version” — they answer three different questions, and only the middle one governs whether HA WebSocket behaves the way this guide describes.

Who does what when a light should turn on

Picture a motion sensor and a hallway light such as light.living_room, and an automation meant to turn the light on when someone walks through at night. Four layers touch that one event, and each has its own job:

  • Home Assistant: the authority for what the sensor and the light actually are. Writing a name on the Node-RED canvas does not create a device.
  • HA WebSocket 0.80.3: the bridge. It subscribes to state events, queries other entities, and asks Home Assistant to turn the light on through the Action node. Older documentation and older flows may still call this the Call Service node — this guide uses its current name, Action, throughout.
  • Node-RED 5.0.2: the runtime that routes the message through nodes and wires and evaluates whatever conditions you built. Each msg is a JavaScript object, not one line of text — it can carry payload, topic, _msgid, and more.
  • Add-on 22.0.1: the deployment package underneath all of it. It provides the data paths, the proxy, the permissions, and the preinstalled packages — and it has no opinion on whether your automation is a good idea.

A report that says only “the light didn't turn on” could point at any one of those four. Working out which layer is actually at fault, before you touch anything, is far faster than restarting the Add-on and hoping.

Edit, Deploy, and restart are three different reaches

Moving nodes around the canvas changes only what the editor is showing you. Clicking Deploy sends the scope you chose to the runtime, which is the first point any of it actually runs. Restarting the Add-on is a third, larger action again: it rebuilds the services around the runtime, not just the flows inside it. The official documentation tells you to restart the Add-on after changing its own configuration — that is a different act from Deploy, and it can affect timers, event subscriptions, and anything with an external side effect in a way a plain Deploy does not.

flowchart LR
  A["Move a node on the canvas.
Changes only the editor state"] --> B["Click Deploy.
Sends the chosen scope to the runtime"] B --> C["Restart the Add-on.
Rebuilds the services around the runtime"]
Three reaches, not oneThree boxes in a straight line, each one wider than the last. Nothing before the second box has touched the running flow at all, and nothing before the third box has touched anything outside Node-RED itself.
In plain terms

It is the difference between editing a document, printing it, and rebooting the whole print room. Dragging a node around is like typing in a Word file that nothing downstream has read yet. Deploy is sending the finished page to the printer, which reacts to it immediately. Restarting the Add-on is cutting power to the entire print room — every printer, every queued job — because sometimes that is the only thing that clears a state nothing else will touch.

Authentication boundaries follow the same pattern of “looks like one thing, is actually several.” Home Assistant Ingress, a direct listener, the editor route, HTTP endpoints your own flows create, static content, and the optional dashboard each answer to a different check. Opening the editor safely from the Home Assistant sidebar does not mean every other door got the same lock. The rest of this part is that distinction, in detail.

The install sequence, in order

Install, Start, check the log, then Open Web UI — in that order

The Add-on comes with a Home Assistant server connection already configured. The safest first move is not to paste in a YAML example from somewhere online; it is to follow the official sequence exactly once, with nothing added, and confirm each step before the next.

  1. Step 1

    Open the Add-on page and confirm the name

    Use the Add-on details page to confirm you are installing Home Assistant Community App: Node-RED, not a separate Node-RED install on another host, and not a container image from an unfamiliar source.

  2. Step 2

    Select Install, and add nothing else yet

    Wait for installation to finish before touching npm_packages, system_packages, or init_commands. 22.0.1 declares support only for aarch64 and amd64; there is no supported workaround for other hardware.

  3. Step 3

    Start it, and let initialization finish untouched

    On first startup the Add-on creates what it needs under /config and runs its own migration for legacy data and themes. If /config/package.json already exists, it also tries to remove three conflicting legacy packages and logs a warning if it cannot. Do not edit files by hand while this is running.

  4. Step 4

    Read the log before you decide anything failed

    The official sequence checks the log before declaring success. Look for a clean start or a specific error. Redact tokens, hostnames, URLs, and message payloads before you ever share a screenshot of it, and do not mash Start again just because the editor has not opened yet.

  5. Step 5

    Select OPEN WEB UI

    The documentation is explicit that you do not need to add, change, or re-enter the server connection. Do not paste a token in just to feel like you finished a step.

  6. Step 6

    Leave the default entry point alone, and write down what you saw

    Do not expose a direct port yet. Record the Add-on version and whether Ingress opened cleanly, then move on to the editor tour and the side-effect-free flow in the next part of this guide.

What the container can already do

Before you install a single extra node, the manifest has already granted the container a set of capabilities that have nothing to do with your flows yet:

DeclarationExact valueHow to read it
Supervisor APIhassio_api: true, hassio_role: managerA highly privileged Supervisor capability. Never expose its token
Home Assistant APIhomeassistant_api: trueThe container can reach Home Assistant Core's API. That is not a reason to hard-code a token in a flow
Authentication APIauth_api: trueThe wrapper can use Supervisor authentication. That does not mean it covers every route
Networkhost_network: trueWider reach into the local network. Keep HTTP, MQTT, TCP/UDP, and discovery use to the minimum you actually need
Serialuart: trueUART access is available. Use it only for a specific, planned device

These are grants to the container, not permission slips for every flow. Once you install a third-party node it runs with the same process privileges as everything else here — an approved Add-on does not make every npm package on the palette trustworthy. The pinned manifest also locks bcryptjs at 3.0.3 and js-yaml at 5.2.2: the former hashes the wrapper's Basic Authentication, the latter supports the runtime itself. Neither is a node you drag onto a canvas, and neither implies every route shares one login.

Data maps, and what a backup does not include

MapModeSecurity implication
addon_configrw/config holds flows, settings, nodes, and credentials. Restrict who can read it
homeassistant_configrwThe Add-on can read and write Home Assistant's own configuration. Do not let an ordinary flow touch it freely
mediarwValidate filenames and paths before writing untrusted content here
sharerwOther add-ons may reach this map too. Do not store plaintext secrets in it
sslNot marked rwDirect TLS reads certificates and keys from here. Never let a flow or a log echo a private key

The manifest's backup_exclude setting drops node_modules. A backup is therefore not a byte-for-byte copy of the running container — after a restore, any custom npm packages have to be reinstalled from a version-pinned list you kept yourself, and the system deserves a real check afterward rather than an assumption that everything came back exactly as it was.

The three-stage boot order, and why one failure stops all of it

Every startup runs a fixed, fail-fast sequence: system_packages, then npm_packages, then init_commands. If any single package install or command in that chain fails, initialization stops right there — it does not skip ahead and try the rest.

flowchart LR
  A["system_packages"] --> B["npm_packages"] --> C["init_commands"] --> S["Normal startup continues"]
  A -.->|"fails"| X["Initialization stops.
Later stages never run"] B -.->|"fails"| X C -.->|"fails"| X
One failure box, reached three waysThe solid chain across the top is the only path to Normal startup continues. Three dotted lines, one leading out of each stage, all land on the same failure box — a bad entry in system_packages stops the Add-on just as completely as a bad one in init_commands does.

init_commands runs each line through a shell eval on every single startup. That is arbitrary command execution by design — keep the array empty unless you have a specific, reviewed reason not to, and never put a secret in one of its lines.

Ingress, direct access, and the doors between

Getting in through the sidebar is not the same door as getting in through a port

The Add-on runtime binds the actual Node-RED backend to 127.0.0.1:46836, uses /config/ as its user directory, /config/nodes for extra nodes, flows.json as the flow file, and fixes httpNodeRoot at /endpoint. Inside Node-RED's own settings, adminAuth and https are both null — authentication and TLS are handled one layer up, by the wrapper and NGINX. That delegation is not the same thing as “safe to expose.”

LayerPurposeVerifiable behavior in 22.0.1
Home Assistant IngressOpen the editor from the HA sidebarManifest sets ingress: true, dynamic ingress_port: 0, ingress_stream: true. NGINX restricts the Ingress listener to the Supervisor's own Ingress address
Direct accessMap the web interface straight to the hostContainer port 80/tcp is exposed, host port 1880 recommended. The Network setting decides whether it is on at all
Direct TLSEncrypt the direct listenerssl, certfile, keyfile apply only to direct access. Ingress is untouched by any of them
Direct editor authenticationProtect the editor on the direct pathThe wrapper and NGINX use Supervisor authentication by default. leave_front_door_open is the switch that removes it — do not use it
Flow HTTP authenticationProtect /endpoint/ routes your own flows createGuarded by the http_node username and password — a separate check from the editor login
Static-content authenticationProtect Node-RED's static filesGuarded by http_static, independent of both authentication layers above it
In plain terms

Coming in through the Home Assistant sidebar is walking through a reception desk that already phoned ahead about you. Opening a direct port is unlocking the loading dock around the back, where nobody called ahead at all — and even that loading dock is really two doors, not one. One is the office door with a badge reader, which is the editor's Supervisor login. The other is a service hatch with its own separate, often-forgotten lock: /endpoint/, guarded only by http_node, and by nothing at all if you never set it.

flowchart TD
  A["Open the editor"] --> B{"Through the Home Assistant
sidebar, or a direct host port?"} B -->|"sidebar"| C["Ingress. The Supervisor
already confirmed who you are"] B -->|"direct port"| D["Direct listener on port 1880"] D --> E["ssl: true encrypts the connection.
It does not check who you are"] D --> F["The Supervisor auth wrapper
still guards the editor itself"] D --> G["/endpoint/ routes skip that wrapper.
http_node is the only thing guarding them"]
Four ways this ends, and only one of them is a login you might have skippedOne decision splits the sidebar from a direct port. The direct branch fans out into three separate facts rather than three more decisions: encryption, the editor's own login, and the /endpoint/ routes that the editor's login was never built to cover. That last box is the one people forget exists.
Never enable leave_front_door_open. The official documentation for this pinned version says so in plain terms, and adds explicitly that this holds even on a local network. A local network is not a trust boundary by itself — anything else already on it, compromised or not, reaches the editor the moment this switch is on.

ssl: true only turns on HTTPS for the direct listener, reading certfile (default fullchain.pem) and keyfile (default privkey.pem) from /ssl/. A certificate authenticates the server to the client and encrypts the wire; it proves nothing about who is connecting, and it does not stand in for the editor login or for http_node. The documentation also states plainly that HTTP In nodes and dashboards need direct access under Network and a path starting with /endpoint/ — otherwise Home Assistant's own authentication intervenes. A /endpoint/ prefix by itself is not a security control; you still need TLS, real http_node credentials, input validation, and sensible rate and size limits on anything that path exposes.

Options and the security checklist

Every switch in config.yaml, and the ones that are one-way doors

This table reflects the pinned 22.0.1 config.yaml. A default is listed only where the manifest itself defines one; do not copy the sample credentials in any documentation verbatim, since they are explicitly examples, not real values.

OptionDefault / schemaPurpose and safe use
log_levelOptional, one of trace|debug|info|notice|warning|error|fatalAdd-on log verbosity. Raise it temporarily to troubleshoot, then bring it back down — logs can carry message data
credential_secretOptional password, no explicit defaultEncrypts credentials Node-RED stores. Keep it safe once set — changing it is covered below
themedefaultEditor appearance only, not a security control. Restart the Add-on after changing it
http_node.username / passwordEmpty stringsProtects flow-created /endpoint/ routes, reachable only over direct access. Separate from the editor login — use real, unique credentials
http_static.username / passwordEmpty stringsProtects static content only, nothing else
ssltrueTLS on the direct listener. No effect on Ingress, and no substitute for a real security review
certfilefullchain.pemUnder /ssl/. The Add-on does not issue or renew it — verify it yourself
keyfileprivkey.pemUnder /ssl/. Never export or log its contents
system_packages[]Extra Alpine packages at startup. More supply-chain surface, more native code, slower boot
npm_packages[]Extra npm packages at startup. Pin versions, review the maintainer, leave empty at first
init_commands[]Shell eval on every startup. Arbitrary command execution — no secrets, leave empty at first
leave_front_door_openOptional bool, no explicit defaultBypasses Supervisor auth on the direct editor. Do not enable it, ever
safe_modeOptional boolPasses --safe: the runtime starts, flows do not. A recovery tool, not a permanent state
max_old_space_sizeOptional intV8 old-space size in MB, not the container's total memory limit. Do not set it blind
In plain terms

Changing credential_secret is re-keying a lock and burning the old key without cutting a spare. Every credential Node-RED had already encrypted with the old key stops decrypting the instant you save the new one — not eventually, not with a warning, the moment it takes effect. There is no “undo” here; there is only re-entering every credential again with the new key already in place.

The theme list is fixed and long — 35 names in the schema, from default and dark through dracula, tokyo-night, and oled. The initialization program migrates a legacy dark setting to dark-modern automatically; for a fresh configuration, just pick a current name from the list.

The checklist for the first configuration, and every change after it

  • Start with theme: default, ssl: true, and the default certificate filenames. Leave system_packages, npm_packages, and init_commands as empty arrays until you have a real, reviewed reason to fill one.
  • Leave the direct host port unmapped. If a real requirement forces it open, verify direct TLS, the editor login, http_node, and http_static separately, and restrict which network sources can even reach the port.
  • Never enable leave_front_door_open. Use safe_mode only as a temporary recovery step, and review every node with a side effect before turning it back off.
  • Keep a controlled, secure copy of credential_secret. It never belongs in a flow, a screenshot, or a repository, and it is not something you change casually once real credentials depend on it.
  • Record the purpose and the rollback value before every configuration change. Restart the Add-on afterward as the documentation requires, read the log, then open the Web UI — and pick a maintenance window if real household automations already depend on this being up.
  • Plan around backup_exclude: node_modules. Keep a version-pinned list of any custom packages, and actually rehearse a restore rather than assuming it will just work the day you need it.
When something doesn't add up

The failures that actually happen, matched to the layer that caused them

SymptomLikely causeWhat to do
You see 22.0.1 but can't find some “Node-RED 22” feature 22.0.1 is the Add-on version, not Node-RED's Check the editor and core-node behavior against Node-RED 5.0.2's own documentation instead
The Add-on installs, but an HA node behaves oddly 2023.3.0 in the manifest is only the install threshold Confirm your Home Assistant is actually at 2024.3+, the real prerequisite for HA WebSocket 0.80.3, then check a redacted Add-on log
The palette has no Dashboard nodes FlowFuse Dashboard 2 1.30.2 is optional and not bundled That is expected. You do not need it for the early chapters of this guide
The Install button is unavailable Home Assistant version or CPU architecture does not meet 22.0.1's manifest Check the Home Assistant version and confirm your hardware is aarch64 or amd64. Do not edit the manifest to bypass this
OPEN WEB UI does nothing after Start Initialization has not finished, or a custom package/command failed Read the Add-on log first. Adding a direct port is not a first remedy for this
Ingress opens the editor, but an HTTP In endpoint is unreachable That is intentional, separate design, not a bug Enable direct access under Network, use a path starting with /endpoint/, and set real TLS and http_node credentials before relying on it
Direct access shows a certificate error Bad certfile/keyfile, expired certificate, or a mismatched key Check the files under /ssl/ and the certificate's validity. Do not disable TLS or fall back to plain HTTP to make the error disappear
Credentials stop working after changing credential_secret That change is one-way by design — old credentials cannot be decrypted with a new key Restore the credentials from your own controlled backup. Do not keep changing the value hoping it resolves itself
Startup gets slow or fails after adding a package A failure partway through system_packages → npm_packages → init_commands Remove the most recently added entry and restart, one change at a time, rather than adding more on top
A flow causes problems the instant it starts Something with a side effect runs on startup Set safe_mode: true, restart, fix the flow with nothing running, then review every Action, HTTP, file, and device node before turning Safe Mode back off
Questions people ask

The ones that come up again and again

Do the Add-on and the Node-RED runtime share a version number?
No. 22.0.1 is the Home Assistant Community App. Its pinned package manifest happens to bundle Node-RED 5.0.2, which is a separate project with its own release cycle.
Should I follow guidance written for a newer Node-RED patch release?
Not by default. Check what the Add-on actually bundles first. If it is still 5.0.2, read its behavior against this guide's pinned sources. Only move to a newer patch after your own process approves it, backs the system up, and re-tests the editor, Deploy, and core nodes with a side-effect-free flow.
Why is FlowFuse Dashboard 2 missing after I install the Add-on?
@flowfuse/node-red-dashboard 1.30.2 is optional and is not one of 22.0.1's direct dependencies. You do not need it for the material in this part or the next.
Should I hand-edit an old flow's api-call-service type to action?
No. In HA WebSocket 0.80.3 the palette and UI name is Action, but compatibility data may still store the older type internally. Let the editor handle that migration rather than editing the persisted flow file by hand.
Do I need to add a Home Assistant server or token after installing?
No. The 22.0.1 documentation is explicit that the server connection is preconfigured and ready to use. Do not hard-code a token during setup just because it feels like an expected step.
Does ssl: true make Ingress and every endpoint secure?
No. It only turns on TLS for the direct listener and has zero effect on Ingress. TLS, the editor login, http_node, and http_static are four separate controls, and turning one on says nothing about the other three.
Can I enable leave_front_door_open if only my home network can reach it?
No. The pinned official documentation advises against it even when exposure is limited to a local network, and this guide gives no procedure for turning it on. Treat “only my home network” as a convenience, not a security boundary.
Why does /endpoint/ need its own username and password?
The direct-access NGINX template does not apply the editor's Supervisor authentication to flow-created HTTP routes. http_node is the only check standing in front of them, so it needs real credentials of its own — plus TLS, input validation, and sensible network restrictions if the route matters at all.
What should I check first if startup keeps failing after I add a package?
Find which of the three stages — system_packages, npm_packages, init_commands — actually failed in the log, remove the most recently added entry, and restart. Do not keep stacking more packages on top, and do not raise the memory limit to paper over what is really a version or compilation error.
Does a backup contain every npm package I installed?
Not by itself. The manifest's backup_exclude drops node_modules, so after a restore you rebuild any custom dependency tree from your own version-pinned list and verify the flows again before trusting them.
What should I ask when a colleague reports only “Node-RED 22”?
Obtain the Add-on, Node-RED, HA WebSocket, Home Assistant, and Node.js versions separately. Then record whether the issue occurs during installation, in the editor, in the runtime, or in a Home Assistant node. Do not begin an upgrade or reinstallation based on an ambiguous version number.
Next

Where to go from here

the door is shut, now open the workspace

The Add-on is installed, the log is clean, and none of the extra doors are open. Nothing has run a single flow yet.

Part 2 stays inside the editor itself: the workspace, the Palette, and the three different scopes Deploy can send — without clicking Deploy once, so nothing on your system reacts. Then it builds your first flow, Inject → Change → Debug, which produces exactly one message and one line of output, and touches no device at all.

Open the full guide

Part 1 of the WoowTech Complete Node-RED Guide series on the Apporo blog.

Adapted from the WoowTech Complete Node-RED Guide, produced by WoowTech and released under CC BY 4.0. This adaptation is published by Apporo under the same licence.

Light · Air · Water · Control · apporo

Back up the right things, then find out what is actually slow