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
- Prerequisites
- Step 1 — Create the data folder
- Step 2 — Start Node-RED with Docker Compose
- Step 3 — Protect the editor with a password
- Step 4 — Protect HTTP endpoints (optional)
- Step 5 — Publish Node-RED over HTTPS with Caddy
- Step 6 — Install additional nodes
- Step 7 — Enable projects with Git (optional)
- Alternative: install without Docker
- Back up and restore
- Update Node-RED
- Troubleshooting
- Error: EACCES: permission denied on /data
- The editor shows Lost connection to server
- Forgot the editor password
- A node fails to install from the palette
- Node-RED crashes on start after deploying a flow
- 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
- A server running Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 12 or Debian 13 with Docker Engine and the Compose plugin. See Install Docker on Ubuntu or Install Docker on Debian.
- A non-root user with
sudorights and SSH key login, as set up in Secure a new Linux server and Set up SSH keys. - A subdomain such as
nodered.example.comwhose A (and optionally AAAA) record points at the server. - Caddy on the host, installed with Caddy reverse proxy.
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.
| Resource | Minimum (official) | Suggested starting point |
|---|---|---|
| CPU | Not published | 1 vCPU |
| RAM | Not published | 1 GB |
| Disk | Not published | 10 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:
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-redStep 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:
services:
node-red:
image: nodered/node-red:latest
restart: unless-stopped
environment:
- TZ=Europe/Istanbul
ports:
- "127.0.0.1:1880:1880"
volumes:
- ./data:/dataReplace 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:
docker compose up -d
docker compose logs node-redYou 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:
curl -I http://127.0.0.1:1880The 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:
docker compose exec node-red npx node-red admin hash-pwType the password twice when prompted and copy the hash it prints. Then open settings.js:
sudo nano /opt/node-red/data/settings.jsFind 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:
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:
docker compose restart node-red
curl -s http://127.0.0.1:1880/auth/loginThe 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:
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:
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:
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.comYou 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:
cd /opt/node-red
docker compose exec node-red bash -c "cd /data && npm install node-red-node-email"
docker compose restart node-redThe -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:
environment:
- TZ=Europe/Istanbul
- NODE_RED_ENABLE_PROJECTS=trueRun 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:
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.serviceThe 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:
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.gzThe 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:
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 -dWithout 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:
cd /opt/node-red
docker compose pull
docker compose up -d
docker compose logs --tail=20 node-redThe 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
- Compare Node-RED with n8n for API-centric workflow automation.
- Connect Node-RED to your smart home with Home Assistant in Docker.
- Find servers for your automation stack on the Node-RED hosting page.
- Read the official Node-RED documentation for flow design, the admin API and security settings.
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
- nodered.org/docs/getting-started/docker
- github.com/node-red/node-red-docker
- hub.docker.com/r/nodered/node-red
- nodered.org/docs/user-guide/runtime/securing-node-red
- nodered.org/docs/user-guide/runtime/configuration
- nodered.org/docs/user-guide/runtime/settings-file
- nodered.org/docs/user-guide/runtime/adding-nodes
- nodered.org/docs/user-guide/projects
- nodered.org/docs/getting-started/local
- nodered.org/docs/getting-started/raspberrypi
- nodered.org/docs/faq/node-versions
- github.com/node-red/node-red/blob/master/packages/node_modules/node…