Skip to content

TutorialsAutomation

How to install Node-RED with Docker and a secured editor

Run Node-RED in Docker on Ubuntu or Debian, lock the editor with a bcrypt password, publish it over HTTPS with Caddy and keep flows backed up and updated.

  • Beginner
  • 30 min read
  • Updated

Tested on: Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 12, Debian 13

This guide is not available in your language yet, so it is shown in English.

On this page
  1. Prerequisites
  2. Step 1 — Create the data folder
  3. Step 2 — Start Node-RED with Docker Compose
  4. Step 3 — Protect the editor with a password
  5. Step 4 — Protect HTTP endpoints (optional)
  6. Step 5 — Publish Node-RED over HTTPS with Caddy
  7. Step 6 — Install additional nodes
  8. Step 7 — Enable projects with Git (optional)
  9. Alternative: install without Docker
  10. Back up and restore
  11. Update Node-RED
  12. Troubleshooting
  13. Error: EACCES: permission denied on /data
  14. The editor shows Lost connection to server
  15. Forgot the editor password
  16. A node fails to install from the palette
  17. Node-RED crashes on start after deploying a flow
  18. Next steps

Node-RED is a low-code programming tool for event-driven applications. You wire nodes together in a browser-based flow editor to connect devices, APIs and online services, which makes it popular for IoT, home automation, data collection and small integrations. Flows are stored as JSON and run on Node.js.

This guide runs Node-RED from the official nodered/node-red Docker image, which is the method Node-RED documents for containers. You keep all data in one folder, publish the editor only on 127.0.0.1, protect it with a bcrypt-hashed password, and put Caddy in front of it for HTTPS. You also install extra nodes, enable the optional Git-based projects feature, and set up backups and updates. A short section explains the official Linux install script if you prefer to run Node-RED directly on the host.

Prerequisites

The Node-RED project does not publish minimum hardware requirements; it runs on devices as small as a Raspberry Pi. What you need depends on your flows and on the nodes you install. Treat these figures as a conservative starting point for a server that runs Node-RED next to a few other containers.

ResourceMinimum (official)Suggested starting point
CPUNot published1 vCPU
RAMNot published1 GB
DiskNot published10 GB SSD

Step 1 — Create the data folder

Node-RED stores flows, credentials, settings and installed nodes in /data inside the container. Map that to a host folder so you can edit settings.js and back it up easily. The container runs as the node-red user with UID 1000, so the folder must belong to UID 1000:

Bash
sudo mkdir -p /opt/node-red/data
sudo chown $USER:$USER /opt/node-red
sudo chown -R 1000:1000 /opt/node-red/data
cd /opt/node-red

Step 2 — Start Node-RED with Docker Compose

Create /opt/node-red/compose.yaml. It uses the official image, publishes port 1880 on the loopback address only and sets the timezone that inject nodes and time functions use:

YAML
services:
  node-red:
    image: nodered/node-red:latest
    restart: unless-stopped
    environment:
      - TZ=Europe/Istanbul
    ports:
      - "127.0.0.1:1880:1880"
    volumes:
      - ./data:/data

Replace Europe/Istanbul with your own IANA timezone. The latest tag follows the newest release on the default Node.js version; the image also comes as -minimal variants without Python and build tools, Node.js-specific tags such as latest-22, and a Debian-based latest-debian image for nodes that do not build on Alpine. To pin a release, use a version tag from Docker Hub instead, for example nodered/node-red:5.0.8.

Start the container and look at the log:

Bash
docker compose up -d
docker compose logs node-red

You should see Settings file : /data/settings.js, User directory : /data and a line saying that the server is now running on port 1880. On first start Node-RED copies a default settings.js into /data, which you edit in the next step. Check the editor from the server:

Bash
curl -I http://127.0.0.1:1880

The response should be HTTP/1.1 200 OK.

Step 3 — Protect the editor with a password

Node-RED's documentation is explicit that the editor is not secured by default: anyone who can reach it can deploy flows, and flows can run commands. Turn on the adminAuth setting before the editor goes online.

First create a bcrypt hash of your password. The image contains the Node-RED admin tool, so you do not need Node.js on the host:

Bash
docker compose exec node-red npx node-red admin hash-pw

Type the password twice when prompted and copy the hash it prints. Then open settings.js:

Bash
sudo nano /opt/node-red/data/settings.js

Find the commented-out //adminAuth block in the Security section and replace it with the following, pasting your hash as the password value. permissions: "*" gives full access; a second user with permissions: "read" would get a read-only view:

Text
    adminAuth: {
        type: "credentials",
        users: [{
            username: "nodered-admin",
            password: "paste-the-bcrypt-hash-here",
            permissions: "*"
        }]
    },

Restart Node-RED and confirm that the admin API now asks for credentials:

Bash
docker compose restart node-red
curl -s http://127.0.0.1:1880/auth/login

The response now contains "type":"credentials". If Node-RED does not start, a missing comma in settings.js is the usual cause; docker compose logs node-red shows the line. Access tokens expire after seven days by default; set sessionExpiryTime (in seconds) in settings.js to change that.

Step 4 — Protect HTTP endpoints (optional)

Flows that use HTTP In nodes serve their own URLs, and these stay public even when the editor is locked. If they should not be open to everyone, set httpNodeAuth, which uses the same bcrypt hash format. Generate a separate hash with the command from Step 3 and add this line to settings.js:

Text
    httpNodeAuth: {user:"api-user", pass:"paste-the-bcrypt-hash-here"},

Static files served through httpStatic can be protected the same way with httpStaticAuth. Restart the container after every change to settings.js. For public webhooks that other services call, leave httpNodeAuth off and validate a secret header or token inside the flow instead.

Step 5 — Publish Node-RED over HTTPS with Caddy

Add a site block to /etc/caddy/Caddyfile. Caddy proxies the WebSocket connection that the editor uses for live updates without extra settings:

Caddyfile
nodered.example.com {
    reverse_proxy 127.0.0.1:1880
}

Reload Caddy, allow only SSH and web traffic in the firewall, and test the result:

Bash
sudo systemctl reload caddy
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
curl -I https://nodered.example.com

You should get HTTP/2 200 with a valid certificate. Open the address in a browser and log in with the user from Step 3. Port 1880 stays closed to the internet because the container only listens on 127.0.0.1. If you use Nginx instead, the proxy must forward the Upgrade and Connection headers for WebSockets; see Nginx with Certbot.

Step 6 — Install additional nodes

The easiest way is the Palette Manager: open the main menu, choose Manage palette, switch to the Install tab and search for a module. The flow library at flows.nodered.org lists the available nodes. Packages are installed into /data, so they survive container updates.

From the command line, run npm install inside the container in /data and restart Node-RED so the new nodes load:

Bash
cd /opt/node-red
docker compose exec node-red bash -c "cd /data && npm install node-red-node-email"
docker compose restart node-red

The -minimal image variants have no Python or build tools and cannot install nodes that compile native code. Use the default or -debian image if you need such nodes.

Step 7 — Enable projects with Git (optional)

The projects feature turns your flows into a Git repository: you commit changes from the editor's History tab and push them to a remote such as a self-hosted Gitea. The official image already contains git and ssh-keygen, which the feature needs. Enable it with an environment variable:

YAML
    environment:
      - TZ=Europe/Istanbul
      - NODE_RED_ENABLE_PROJECTS=true

Run docker compose up -d to apply the change. The editor then offers to create your first project. When it asks for a credentials encryption key, choose a strong one and store it in your password manager: the key is not saved in the repository, and anyone who clones the project needs it to decrypt the credentials.

Alternative: install without Docker

Node-RED also maintains an official install script for Debian-based systems, including Ubuntu and Debian. It removes an existing Node-RED install, makes sure Node.js 20 or newer is present (installing Node.js 22 LTS from NodeSource if it is missing), installs the latest Node-RED with npm and sets it up as the nodered systemd service with helper commands such as node-red-start, node-red-stop and node-red-log. This route is useful when flows need direct access to hardware such as serial devices.

Download the script, read it, then run it as your normal sudo user. --help lists its options:

Bash
sudo apt install build-essential git curl
curl -fsSL https://github.com/node-red/linux-installers/releases/latest/download/install-update-nodered-deb -o install-nodered.sh
less install-nodered.sh
bash install-nodered.sh
sudo systemctl enable --now nodered.service

The official one-line equivalent pipes the same file straight into bash. With this method the user directory is ~/.node-red, node-red admin hash-pw works directly on the host, and Node-RED listens on all interfaces by default. Set uiHost: "127.0.0.1", in ~/.node-red/settings.js so that only Caddy can reach port 1880, configure adminAuth as in Step 3 and restart with node-red-restart. Run the script again to upgrade.

Back up and restore

Everything Node-RED needs is in /opt/node-red/data: flows.json, the encrypted credentials file flows_cred.json, settings.js, package.json with the list of installed nodes, the nodes themselves and the key Node-RED generated to encrypt credentials. Archive the whole folder, hidden files included, together with compose.yaml:

Bash
sudo mkdir -p /opt/backups
sudo tar czf /opt/backups/node-red-$(date +%F).tar.gz -C /opt/node-red data compose.yaml
sudo chmod 600 /opt/backups/node-red-*.tar.gz

The archive can be taken while Node-RED runs. Copy it to another machine or object storage, because a backup that stays on the same server is lost with the server.

To restore, stop the container, replace the folder and fix the ownership:

Bash
cd /opt/node-red
docker compose down
sudo rm -rf /opt/node-red/data
sudo tar xzf /opt/backups/node-red-2026-10-09.tar.gz -C /opt/node-red
sudo chown -R 1000:1000 /opt/node-red/data
docker compose up -d

Without the generated credential key, the flows load but every saved credential is lost. If you move flows between servers often, set your own credentialSecret in settings.js and keep it in your password manager.

Update Node-RED

Read the release notes on the Node-RED blog before a new major version; Node-RED 5, for example, requires Node.js 22 or newer, which the Docker image already provides. Back up the data folder, then pull the new image and recreate the container:

Bash
cd /opt/node-red
docker compose pull
docker compose up -d
docker compose logs --tail=20 node-red

The log shows the new Node-RED and Node.js versions. If you pinned a version tag, change it in compose.yaml first. Installed nodes stay in /data; update them from Manage palette, where outdated modules show an update button. If a node with native code fails after a Node.js upgrade, rebuild it with docker compose exec node-red bash -c "cd /data && npm rebuild".

Troubleshooting

Error: EACCES: permission denied on /data

The host folder does not belong to UID 1000, the user inside the container. Run sudo chown -R 1000:1000 /opt/node-red/data and start the container again. This often happens after restoring a backup as root or copying files in with sudo cp.

The editor shows Lost connection to server

The browser cannot keep the WebSocket connection to Node-RED open. Caddy handles WebSockets automatically; with Nginx you must pass the Upgrade and Connection headers and use HTTP/1.1 for the proxy connection. Also check that nothing between the browser and the server, such as a CDN or firewall, blocks WebSockets.

Forgot the editor password

Generate a new hash with docker compose exec node-red npx node-red admin hash-pw, replace the password value in /opt/node-red/data/settings.js and run docker compose restart node-red. Flows and credentials are not affected.

A node fails to install from the palette

Read the error in docker compose logs node-red. Nodes with native components need Python and build tools, which the -minimal images do not contain; switch to the default or -debian tag. Also check that the node supports your Node-RED and Node.js versions.

Node-RED crashes on start after deploying a flow

A faulty flow or node can stop the runtime from starting. Set NODE_RED_ENABLE_SAFE_MODE=true in the environment list and run docker compose up -d: Node-RED starts without running the flows, so you can fix or delete the problem in the editor. Remove the variable again afterwards.

Next steps

Frequently asked questions

Is the Node-RED editor password protected by default?

No. Node-RED's documentation states that the editor is not secured by default, so anyone who can reach port 1880 can change and deploy flows. Set adminAuth in settings.js before you expose the editor, and publish the port only on 127.0.0.1.

Should I use Docker or the official install script?

Both are official. Docker keeps Node.js and Node-RED inside one image and makes updates a simple pull. The Linux install script installs Node.js and Node-RED directly on the server and creates a systemd service, which suits hardware access such as serial ports.

How do I install extra nodes in Docker?

Use Manage palette in the editor menu, which installs packages into the /data folder. From the command line you can run npm install inside the container in /data and restart Node-RED. Nodes with native code need the default image, not the minimal variant.

What do I need to back up for Node-RED?

Everything lives in the /data folder: flows.json, the encrypted credentials file, settings.js, package.json and the installed nodes, plus the generated credential key. Archive the whole folder, hidden files included, and keep a copy off the server.

Does Node-RED run on a HyperDC server?

Yes. This guide works on a HyperDC Linux VPS, VDS or dedicated server with root access running Ubuntu 24.04, Ubuntu 26.04, Debian 12 or Debian 13. Node-RED itself is light, so size the server for the flows and other services you run.

Sources

Generer adgangskode

Please confirm