← All articles
A computer generated image of a cluster of spheres

Node-RED: Visual Automation That Connects Everything in Your Homelab

Automation 2026-02-13 · 11 min read node-red automation flows mqtt iot self-hosted visual-programming
By Selfhosted Guides Editorial TeamSelf-hosting practitioners covering open source software, home lab infrastructure, and data sovereignty.

Your homelab has a temperature sensor publishing data over MQTT, a media server that should pause downloads when bandwidth gets tight, a security camera that needs to trigger notifications, and a dashboard that should display it all in real time. You could write a Python script for each connection, maintain a cron job for each check, and debug a different logging format for each piece. Or you could wire it all together visually in an afternoon.

Photo by Logan Voss on Unsplash

Node-RED is a flow-based programming tool that lets you connect hardware devices, APIs, and services by dragging wires between nodes on a canvas. Originally built by IBM for IoT prototyping, it has grown into a general-purpose automation engine with over 5,000 community-contributed nodes covering everything from MQTT brokers to Slack bots to machine learning pipelines.

Where tools like n8n focus on SaaS-to-SaaS integrations and Home Assistant focuses on smart home control, Node-RED sits in a unique spot: it is equally comfortable talking to a temperature sensor on a Raspberry Pi, processing webhooks from GitHub, and building a custom dashboard with live charts. If your automation needs cross the boundary between physical hardware and software services, Node-RED is probably the right tool.

Node-RED flow-based automation tool logo

Node-RED vs the Alternatives

Feature Node-RED n8n Home Assistant Automations Huginn
Primary focus IoT + general automation SaaS workflow automation Smart home control Web scraping + agents
Interface Flow canvas (wires + nodes) Visual workflow editor YAML + visual editor Web UI (agent config)
Protocol support MQTT, TCP, UDP, WebSocket, serial HTTP/webhooks Zigbee, Z-Wave, MQTT, HTTP HTTP
Community extensions 5,000+ nodes 400+ integrations 2,000+ integrations ~50 agent types
Custom code JavaScript (function nodes) JavaScript + Python Jinja2 templates, Python Ruby
Dashboard/UI Built-in dashboard nodes No Built-in dashboards No
Hardware access Serial, GPIO, USB No Via add-ons No
Real-time data Yes (WebSocket, MQTT streams) Polling/webhook-based Yes (state changes) Polling-based
Self-hosted Yes (free, Apache 2.0) Yes (free, source-available) Yes (free, Apache 2.0) Yes (free, MIT)
Learning curve Low-Medium Low Medium (YAML-heavy) High
Resource usage ~100-250 MB RAM ~200-400 MB RAM ~500 MB-2 GB RAM ~500 MB RAM

When to choose Node-RED

Pick Node-RED when your automations involve MQTT, hardware sensors, serial devices, or real-time data streams. It excels at IoT scenarios where you need to subscribe to a topic, transform a message, and route it somewhere else in milliseconds. The function nodes give you full JavaScript when visual wiring is not enough, and the built-in dashboard lets you create monitoring UIs without a separate tool.

Node-RED is also the right choice when you want a lightweight automation layer that does not need a database. Out of the box, it stores everything as flat JSON files. You can have it running in 30 seconds on a Raspberry Pi Zero.

When to choose something else

If your primary need is connecting SaaS products (Slack to Google Sheets, Stripe webhooks to a database), n8n has better pre-built integrations and a more polished credential management system.

If you are automating a smart home with Zigbee/Z-Wave devices and want presence detection, room-aware logic, and a mature mobile app, Home Assistant is purpose-built for that. Node-RED is a popular companion to Home Assistant (there is an official add-on), but it is not a replacement for the device management layer.

If you need autonomous web scraping agents that monitor websites and act on changes over days or weeks, Huginn is designed around that agent model. Node-RED can do web scraping, but it was not designed for long-running stateful agents.

Installation via Docker Compose

# docker-compose.yml
services:
  nodered:
    image: nodered/node-red:latest
    ports:
      - "1880:1880"
    volumes:
      - nodered_data:/data
    environment:
      - TZ=America/Los_Angeles
    restart: unless-stopped

volumes:
  nodered_data:
docker compose up -d

Node-RED is available at http://your-server:1880. The flow editor loads immediately with no setup wizard.

Adding an MQTT broker

Most Node-RED deployments pair with an MQTT broker. Add Mosquitto to the same compose file:

# docker-compose.yml
services:
  nodered:
    image: nodered/node-red:latest
    ports:
      - "1880:1880"
    volumes:
      - nodered_data:/data
    environment:
      - TZ=America/Los_Angeles
    depends_on:
      - mosquitto
    restart: unless-stopped

  mosquitto:
    image: eclipse-mosquitto:2
    ports:
      - "1883:1883"
    volumes:
      - mosquitto_data:/mosquitto/data
      - mosquitto_config:/mosquitto/config
    restart: unless-stopped

volumes:
  nodered_data:
  mosquitto_data:
  mosquitto_config:

Create a Mosquitto config before starting:

mkdir -p mosquitto_config
cat > mosquitto_config/mosquitto.conf <<EOF
listener 1883
allow_anonymous false
password_file /mosquitto/config/passwords
persistence true
persistence_location /mosquitto/data
EOF

# Create a password file
docker run --rm -v $(pwd)/mosquitto_config:/mosquitto/config \
  eclipse-mosquitto:2 mosquitto_passwd -c /mosquitto/config/passwords myuser

In Node-RED, configure the MQTT nodes to connect to mosquitto:1883 (using the Docker service name) with the credentials you just created.

Core Features

The flow editor

The flow editor is a browser-based canvas where you build automations by dragging nodes from the palette, dropping them onto the workspace, and wiring outputs to inputs. Every node has a specific job: receive an MQTT message, parse JSON, apply a filter, send an HTTP request, write to a file.

Flows read left to right. A trigger on the left fires a message, processing nodes in the middle transform it, and output nodes on the right deliver the result. You can branch flows, merge them, add delays, and route messages conditionally.

Double-click any node to configure it. Click Deploy to push your changes live. Node-RED hot-reloads flows without restarting the runtime.

MQTT integration

MQTT is Node-RED's strongest protocol. The mqtt-in and mqtt-out nodes handle subscriptions and publishing with QoS levels, retained messages, and wildcard topic subscriptions.

A typical IoT flow:

mqtt-in (sensors/temperature/#)
  → json (parse payload)
  → switch (route by sensor ID)
  → change (extract value)
  → dashboard chart (display)
  → mqtt-out (alerts/high-temp) [if threshold exceeded]

This subscribes to all temperature sensor topics, parses the incoming JSON, routes messages by sensor, displays values on a dashboard, and publishes an alert if a reading exceeds a threshold. Building this takes about five minutes in the editor.

HTTP endpoints

Node-RED can create REST APIs with the http-in and http-response nodes. This is useful for building webhook receivers, simple APIs, or proxy endpoints:

http-in (POST /api/webhook)
  → function (validate + transform)
  → http request (forward to another service)
  → http-response (return 200)

You get a fully functional HTTP endpoint without writing a server. This is particularly handy for accepting webhooks from services that do not support MQTT.

Dashboard UI nodes

Install node-red-dashboard (or the newer node-red-dashboard-2 for the FlexDash-based version) from the palette manager to get UI widgets:

The dashboard is accessible at http://your-server:1880/ui and updates in real time over WebSocket. No page refreshes, no polling.

To install from the editor: go to Menu > Manage palette > Install, search for node-red-dashboard, and click install.

Function nodes

When visual wiring is not enough, function nodes give you full JavaScript:

// Example: aggregate sensor readings over 5 minutes
const readings = context.get('readings') || [];
readings.push(msg.payload.temperature);

if (readings.length >= 30) {
    const avg = readings.reduce((a, b) => a + b) / readings.length;
    context.set('readings', []);
    msg.payload = { average: avg, samples: 30 };
    return msg;
}

context.set('readings', readings);
return null; // suppress output until we have enough samples

Function nodes have access to three context scopes:

This is where Node-RED bridges the gap between no-code and code. You drag wires for the simple stuff and drop into JavaScript when you need logic that would be awkward to express as wired nodes.

5,000+ community nodes

The palette manager lets you install community nodes directly from npm. Some popular ones:

Install any of these from the palette manager or by running npm install inside the Node-RED data directory.

Like what you're reading? Subscribe to Self-Hosted Weekly — free weekly guides in your inbox.

Advanced Usage

Subflows

Subflows are reusable flow components. If you find yourself building the same pattern repeatedly (parse MQTT, check threshold, send alert), wrap it in a subflow:

  1. Select the nodes you want to reuse
  2. Go to Menu > Subflows > Selection to Subflow
  3. Define input/output ports and configurable properties
  4. Use the subflow like any other node across your flows

Subflows keep complex deployments maintainable. Instead of 50 copies of the same alert logic, you have one subflow and 50 instances.

Environment variables

Node-RED supports environment variables for configuration that should not be hardcoded:

# docker-compose.yml
environment:
  - TZ=America/Los_Angeles
  - MQTT_BROKER=mosquitto
  - MQTT_PORT=1883
  - [email protected]

Reference them in function nodes with env.get("MQTT_BROKER") or in node configuration fields using ${MQTT_BROKER} syntax.

This lets you use the same flow definitions across development and production environments by changing environment variables instead of editing flows.

Projects feature (Git integration)

Enable the projects feature to version-control your flows with Git:

  1. Set editorTheme.projects.enabled: true in your settings.js
  2. Restart Node-RED
  3. The editor prompts you to create or clone a project

With projects enabled, Node-RED tracks your flows, credentials (encrypted), and package dependencies in a Git repository. You can push to a remote, pull changes, view diffs, and manage branches from inside the editor.

To enable in Docker, mount a custom settings file:

volumes:
  - nodered_data:/data
  - ./settings.js:/data/settings.js

And in settings.js:

module.exports = {
    editorTheme: {
        projects: {
            enabled: true
        }
    }
}

Custom node development

If the 5,000+ community nodes do not cover your use case, building a custom node involves two files:

The official documentation walks through the process. A minimal custom node takes about 30 minutes to build. Package it as an npm module to share with the community or install across your own instances.

Credential management

Node-RED encrypts credentials (passwords, API keys, tokens) stored in node configurations using a key derived from credentialSecret in settings.js. Set this to a strong random value:

module.exports = {
    credentialSecret: "your-random-secret-key-here"
}

Generate one with openssl rand -hex 32. Without this setting, credentials are encrypted with a default key, which is better than plaintext but not secure against someone with access to your flow files.

When exporting flows, credentials are excluded by default. This prevents accidental leaks when sharing flows with others.

Resource Requirements

Setup CPU RAM Storage Notes
Small (< 20 flows, no dashboard) 1 core 128 MB 100 MB Runs on a Pi Zero
Medium (20-100 flows, dashboard, MQTT) 1-2 cores 256-512 MB 500 MB Typical homelab
Large (100+ flows, heavy function nodes) 2+ cores 512 MB-1 GB 1 GB+ Add InfluxDB for time-series
With Mosquitto broker +0 cores +20-50 MB +100 MB Mosquitto is extremely lightweight

Node-RED is one of the lighter automation tools you can run. The Node.js runtime starts at around 80 MB and grows with the number of active flows and installed nodes. The dashboard adds another 30-50 MB when clients are connected.

Honest Limitations

Flow spaghetti is real

Node-RED's visual editor becomes hard to navigate when you have complex logic. Fifty nodes with crossing wires on a single tab is not fun to debug or maintain. The mitigation is discipline: use subflows, organize with named tabs, add comment nodes, and resist the urge to put everything on one canvas.

Debugging is not always intuitive

The debug sidebar shows message payloads flowing through your wires, which is great for simple flows. But when you have parallel branches, asynchronous callbacks in function nodes, and messages firing every second from MQTT, it can be hard to trace which message caused which behavior. Adding debug nodes at strategic points helps, but it is not the same as stepping through code with a debugger.

Node.js memory behavior

Node-RED runs on Node.js, which has a garbage collector that does not always release memory aggressively. Long-running function nodes that accumulate data in context, or flows that process large payloads (images, files), can cause memory to climb over time. Monitor with docker stats and set container memory limits as a safety net.

Security needs explicit attention

Out of the box, Node-RED has no authentication. Anyone who can reach port 1880 can modify your flows. You must enable admin authentication in settings.js:

module.exports = {
    adminAuth: {
        type: "credentials",
        users: [{
            username: "admin",
            password: "$2b$08$your-bcrypt-hash-here",
            permissions: "*"
        }]
    }
}

Generate the password hash with:

docker exec nodered npx node-red-admin hash-pw

Beyond admin auth, also consider:

No built-in execution history

Unlike n8n, Node-RED does not keep a log of every flow execution. There is no "show me what ran at 3 AM and what data it processed." You can add logging with debug nodes or write to an external database, but it is not built in. For critical automations, build explicit logging into your flows.

Practical Tips

Start with one flow and expand. Wire up your most annoying manual task first. Get comfortable with the editor, then tackle more complex automations.

Use link nodes for clean routing. Link-in and link-out nodes let you jump between flow tabs without drawing wires across the entire canvas. Name them clearly.

Set up a catch-all error handler. Add a catch node to each flow tab that sends errors to your notification channel. Without this, errors vanish silently.

Use context stores wisely. Flow and global context persist in memory by default (lost on restart). If you need persistence, configure a file-based or Redis-backed context store in settings.js:

contextStorage: {
    default: { module: "memory" },
    persistent: { module: "localfilesystem" }
}

Then use flow.get('key', 'persistent') and flow.set('key', value, 'persistent') in function nodes.

Back up your flows regularly. The flow files live in /data inside the container. Your Docker volume handles persistence, but export flows periodically as insurance. You can do this from the editor (Menu > Export > All flows) or by copying the flows.json file from the volume.

Pin your Docker image version. Use nodered/node-red:4.0 instead of latest in production. Node-RED major version upgrades can break community nodes. Upgrade deliberately, not accidentally.

Pair with InfluxDB and Grafana for time-series. Node-RED is great at collecting and routing data but not designed for long-term storage or complex visualization. Send your data to InfluxDB with the contrib node, then build dashboards in Grafana for historical analysis. Use the Node-RED dashboard for real-time monitoring and quick controls.

Resources

The Bottom Line

Node-RED fills a specific gap in the self-hosted automation landscape: it connects the physical world to the digital one with minimal friction. If your automations involve MQTT, hardware sensors, serial devices, or real-time data streams, Node-RED handles those natively in a way that SaaS-focused tools simply do not. The visual flow editor makes simple integrations approachable, function nodes provide an escape hatch to full JavaScript when you need it, and the resource footprint is small enough to run on hardware you probably already have sitting in a drawer. Pair it with an MQTT broker and you have an event-driven automation backbone for your entire homelab.

Get free weekly tips in your inbox. Subscribe to Self-Hosted Weekly