Node-RED 5.0.9
Overview
This guide shows you how to launch and use the Node-RED 5.0.9 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud developer and API tools listing on AWS Marketplace. You select it as the software version when you subscribe and launch.
Node-RED is an open-source, low-code programming tool for event-driven applications. In a browser editor, you wire nodes into flows that receive HTTP requests, call APIs, transform messages, talk to MQTT brokers and databases, and run your own JavaScript. You then deploy the flows with one click.
Node-RED runs code. Anyone who signs in to the editor can run any JavaScript (function nodes) and any shell command (exec nodes) on the instance as the node-red service user. Treat the passwords like SSH access, and give them only to people you trust with the instance.
What you get:
- HTTPS from the first boot. nginx serves Node-RED on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
- Two logins before the editor, both unique to your instance. Your browser first asks for an HTTP login (user
admin), then Node-RED's ownadminlogin (user admin, a different password) is switched on. Upstream Node-RED ships with no login at all. Both passwords are generated on first boot and written to/var/lib/sac/data/node-red-credentials.txt(root only); only bcrypt hashes are stored anywhere else. No password is baked into the image. - Your flows' HTTP endpoints are not public by default. HTTP In nodes are served under
/api/and need a third, per-instance login (userapi), checked by nginx and again by Node-RED. You can deliberately make them public (Step 7). - Flow credentials are encrypted with a key unique to your instance (
credentialSecret), generated on first boot. - Flow code is sandboxed. Node-RED and everything a flow starts run as the unprivileged
node-reduser with no capabilities, a read-only view of the system except the data volume, private/tmpand devices, and a memory ceiling. That user cannot read the passwords, the certificate key or the login files. - No route to the instance metadata service. Node-RED, every process a flow starts and nginx are blocked from the EC2 metadata service (IPv4 and IPv6) at the kernel level, so a flow cannot pick up the instance's role credentials.
- Cross-site protection. Another website cannot use your signed-in browser to deploy flows or open the editor's live connection. State-changing requests and WebSocket handshakes from another origin are refused, and the editor's API answers only to the Node-RED sign-in token.
- Nothing installs itself from the internet. The palette manager (installing extra nodes with npm) and npm modules in function nodes are off, and so are telemetry and the update check (Step 12 shows how to switch the palette manager on).
- Current components from pinned sources. Node-RED 5.0.9 installed from a locked, integrity-checked dependency list, with two of its libraries updated to releases that close advisories published after 5.0.9, on the official Node.js 24.22.1 LTS build. No compiler or package manager is left on the image.
- Your flows on their own disk. Node-RED's user directory lives on a separate 20 GiB EBS volume at
/var/lib/node-red. - Fully patched. Ubuntu 24.04 LTS is patched at build time, with unattended security upgrades switched on. The AMI requires IMDSv2.
What is on the image: Node-RED 5.0.9 (/opt/node-red), Node.js 24.22.1 (/opt/nodejs), nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account that is subscribed to the listing, an EC2 key pair and a VPC subnet
- A security group that allows TCP 22 (SSH), TCP 443 (Node-RED) and TCP 80 (redirects to HTTPS) from your own networks only
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Select Node-RED 5.0.9 on Ubuntu 24.04 as the software version and select your Region. Then choose Launch through EC2.
Choose m5.large (2 vCPU, 8 GiB), your key pair and a security group as described above. The AMI includes its own 20 GiB data volume. You can make it larger on the launch page.
To launch with the AWS CLI instead, replace the values in angle brackets:
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=node-red}]'Connect to your instance
Version SSH user
Node-RED 5.0.9 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
On first boot, the instance generates the certificate, the passwords and Node-RED's credential key. Node-RED and nginx then start. Check that first boot has finished:
systemctl is-active node-red nginx node-red-firstboot
sudo test -f /var/lib/sac/data/node-red-firstboot.done && echo FIRSTBOOT_DONEactive active active FIRSTBOOT_DONEOnly SSH and nginx listen on the network. Node-RED listens on 127.0.0.1:1880 only. Confirm this with:
sudo ss -lntp | awk 'NR>1 {print $4, $6}' | grep -v '127.0.0.5' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort0.0.0.0:22 users:(("sshd"),("systemd")) 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) 127.0.0.1:1880 users:(("node-red")) [::]:22 users:(("sshd"),("systemd")) [::]:443 users:(("nginx"),("nginx"),("nginx")) [::]:80 users:(("nginx"),("nginx"),("nginx"))Get your URL and passwords
sudo cat /var/lib/sac/data/node-red-credentials.txtOnly root can read the file. It holds the URL and the three logins:
# Node-RED 5.0.9 - generated on first boot by node-red-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.
# Node-RED RUNS CODE: anyone who signs in to the editor can run any program as the 'node-red' user on this instance. NODE_RED_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/ HTTP_USERNAME=admin HTTP_PASSWORD=<HTTP_PASSWORD> NODE_RED_USERNAME=admin NODE_RED_PASSWORD=<NODE_RED_PASSWORD> API_BASE_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/api/ API_USERNAME=api API_PASSWORD=<API_PASSWORD>
#
# Two walls: your browser first asks for HTTP_USERNAME / HTTP_PASSWORD (nginx), then the Node-RED editor asks for
# NODE_RED_USERNAME / NODE_RED_PASSWORD. Your flows' HTTP In endpoints are served under API_BASE_URL and need # API_USERNAME / API_PASSWORD (sudo node-red-api-auth off makes them public). The certificate is self-signed and minted # on this instance's first boot; compare its fingerprint (sudo openssl x509 -in /etc/ssl/node-red/node-red.crt -noout
# -fingerprint -sha256) with what your browser shows. Port 80 redirects to https.
# Self-test:
sudo node-red-selftest Change the name it is served as:
sudo node-red-set-hostname <your-dns-name>
# User guide: https://secureanycloud.com/stacks/node-red-5-0-9/The URL uses the instance's public DNS name from the EC2 instance metadata. The certificate also names the public and private IP addresses, so https://<public-ip>/ works too. To serve Node-RED under your own DNS name, see Step 10.
The self-test signs in over HTTPS with the logins and checks the protections described in this guide. Run it with:
sudo node-red-selftestSELFTEST-OK https 301 + /health + 401 no/wrong HTTP credential + editor page + Admin API 401 without sign-in + sign-in token + /settings 5.0.9 + /flows + 403 cross-origin POST + 403 cross-origin WebSocket + /api/ 401 without, 404 with the api credential + token revoked + 444 unknown hostSign in
The certificate is self-signed and was generated on your instance, so your browser warns about it the first time. Before you accept it, compare its SHA-256 fingerprint with the one the instance reports. Do not add it to your computer's trust store. Step 10 shows how to use a certificate from your own certificate authority.
sudo openssl x509 -in /etc/ssl/node-red/node-red.crt -noout -fingerprint -sha256sha256 Fingerprint=<32 colon-separated hex pairs, unique to your instance>Open the NODE_RED_URL in your browser. It first asks for a user name and password. Enter admin and the HTTP_PASSWORD. Node-RED then shows its own sign-in page. Enter admin and the NODE_RED_PASSWORD:
The editor opens on an empty flow. The palette on the left lists the nodes you can drag into a flow. The sidebar on the right shows node help, debug messages and deployment information:
Build and deploy a first flow
Drag an inject node and a debug node onto the workspace. Wire the inject node's output to the debug node, then choose Deploy. Select the button on the inject node to send a timestamp. The Debug messages tab in the sidebar shows it:
Node-RED saves flows on the data volume as soon as you deploy. Menu > Export and Menu > Import copy flows between instances as JSON.
Serve an HTTP endpoint from a flow
An http in node with the URL /hello, a template or function node and an http response node give you a web endpoint. Node-RED serves every HTTP In endpoint under /api/, so that flow answers at https://<your-host>/api/hello. It needs the api login from the credentials file:
sudo bash -c ' F=/var/lib/sac/data/node-red-credentials.txt B=$(grep "^API_BASE_URL=" $F | cut -d= -f2-); H=$(echo "$B" | sed -E "s#^https://([^/]+)/.*#\1#") printf "user = \"api:%s\"\n" "$(grep "^API_PASSWORD=" $F | cut -d= -f2-)" > /run/nr-api.cfg; chmod 600 /run/nr-api.cfg curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w "without the api login -> HTTP %{http_code}\n" "${B}hello" curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w "with the api login, nothing deployed at /hello yet -> HTTP %{http_code}\n" -K /run/nr-api.cfg "${B}hello" rm -f /run/nr-api.cfg 'without the api login -> HTTP 401 with the api login, nothing deployed at /hello yet -> HTTP 404The editor's own logins do not open /api/, and the api login does not open the editor.
To make your HTTP endpoints public, switch the api login off. Anyone who can reach port 443 can then call every HTTP In endpoint you deploy. Use on to switch the login back on:
sudo node-red-api-auth off
sudo node-red-api-auth statusWhere your flows live
df -h /var/lib/node-red | tail -1 sudo ls -l /var/lib/node-red /var/lib/node-red/data/dev/nvme1n1 20G 72K 19G 1% /var/lib/node-red /var/lib/node-red: total 24 drwxr-x--- 4 node-red node-red 4096 Oct 28 10:37 data drwxr-x--- 2 node-red node-red 4096 Oct 28 10:36 home drwx------ 2 root root 16384 Oct 28 09:47 lost+found /var/lib/node-red/data: total 12 drwxr-x--- 3 node-red node-red 4096 Oct 28 10:36 lib drwxr-x--- 2 node-red node-red 4096 Oct 28 10:36 node_modules -rw-r----- 1 node-red node-red 120 Oct 28 10:36 package.jsonPath Holds
/var/lib/node-red/data/flows.json your flows
/var/lib/node-red/data/flows_cred.json credentials your nodes use (passwords, API keys), encrypted with this instance's credentialSecret
/var/lib/node-red/data/.sessions.json the editor's sign-in sessions
/var/lib/node-red/data/lib your saved library entries
/var/lib/node-red/home the node-red user's home
The data volume is a separate EBS volume, so you can grow it or snapshot it on its own. To grow it, modify the volume in the EC2 console, then run sudo resize2fs on its device. To copy your flows off the instance, run:
sudo tar -czf <backup-dir>/node-red-flows.tar.gz -C /var/lib/node-red dataOnly this instance's credential key, /etc/node-red/credentials/credential-secret (root only), can decrypt flows_cred.json. To restore the flows' credentials on another instance, keep a copy of the key with your backup.
What flow code can and cannot reach
Function nodes, exec nodes and everything they start run as node-red in the same locked-down service as Node-RED itself. That user cannot read the passwords, the credential key, the certificate key or the login files. Its service, like nginx, is blocked from the instance metadata service. Confirm this from the command line:
for f in /var/lib/sac/data/node-red-credentials.txt /etc/node-red/credentials/admin-hash /etc/node-red/credentials/credential-secret /etc/ssl/node-red/node-red.key /etc/nginx/.node-red-htpasswd /etc/nginx/.node-red-api-htpasswd; do
sudo -u node-red test -r "$f" && echo "readable: $f" || echo "not readable by node-red: $f" done systemctl show node-red -p User -p NoNewPrivileges -p ProtectSystem -p ReadWritePaths -p CapabilityBoundingSet -p MemoryMax for u in node-red nginx; do echo "$u IPAddressDeny: $(systemctl show $u -p IPAddressDeny --value | tr ' ' '\n' | sort | xargs)"; doneMemoryMax is 80% of the instance's memory (here a 4 GiB t3.medium). Node-RED and everything its flows start share it.
not readable by node-red: /var/lib/sac/data/node-red-credentials.txt not readable by node-red: /etc/node-red/credentials/admin-hash not readable by node-red: /etc/node-red/credentials/credential-secret not readable by node-red: /etc/ssl/node-red/node-red.key not readable by node-red: /etc/nginx/.node-red-htpasswd not readable by node-red: /etc/nginx/.node-red-api-htpasswd MemoryMax=3214704640 CapabilityBoundingSet= User=node-red ReadWritePaths=/var/lib/node-red ProtectSystem=strict NoNewPrivileges=yes node-red IPAddressDeny: 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128 nginx IPAddressDeny: 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128To see the block from a flow, import the following into the editor (Menu > Import), deploy it and select the inject node. The exec node asks the metadata service and, as a control, Node-RED's own sign-in endpoint. The debug sidebar shows metadata=HTTP000 (no connection) next to loopback=HTTP200. Delete the flow afterwards.
[{"id":"a1b2c3d4e5f60001","type":"inject","name":"probe","props":[],"repeat":"","once":false,"topic":"","x":120,"y":80,"wires":[["a1b2c3d4e5f60002"]]},{"id":"a1b2c3d4e5f60002","type":"exec","command":"curl -s -m 5 -o /dev/null -w 'metadata=HTTP%{http_code} ' http://169.254.169.254/latest/meta-data/; curl -s -m 5 -o /dev/null -w 'loopback=HTTP%{http_code}' http://127.0.0.1:1880/auth/login","addpay":"","append":"","useSpawn":"false","timer":"20","winHide":false,"oldrc":false,"name":"","x":300,"y":80,"wires":[["a1b2c3d4e5f60003"],[],[]]},{"id":"a1b2c3d4e5f60003","type":"debug","name":"","active":true,"tosidebar":true,"complete":"payload","x":480,"y":80,"wires":[]}]Your own DNS name and certificate
Point a DNS record at the instance, then set the name that Node-RED is served as. This command generates a new self-signed certificate for the name. It updates nginx, the cross-site protection and the URL in the credentials file, and it keeps the name across reboots:
sudo node-red-set-hostname <your-domain>To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx. Running node-red-set-hostname again replaces it with a self-signed certificate:
sudo install -m 0644 <your-domain>.crt /etc/ssl/node-red/node-red.crt
sudo install -m 0600 <your-domain>.key /etc/ssl/node-red/node-red.key
sudo nginx -t && sudo systemctl reload nginxChange the passwords
The HTTP login is an nginx Basic Auth file. To set a new password for admin, pass it to htpasswd on standard input, then reload nginx. printf is a shell builtin, so the password never appears in the process list. Start the line with a space so that most shells keep it out of your history.
The api login works the same way with /etc/nginx/.node-red-api-htpasswd:
printf '%s\n' '<new-password>' | sudo htpasswd -i -B -C 12 /etc/nginx/.node-red-htpasswd admin
sudo systemctl reload nginxNode-RED's own admin password is stored as a bcrypt hash in /etc/node-red/credentials/admin-hash (root only). systemd hands the hash to Node-RED when it starts. This command writes the hash of a new password, read from standard input, and restarts Node-RED:
printf '%s' '<new-password>' | sudo bash -c 'umask 077; /opt/nodejs/bin/node -e "let p=\"\";process.stdin.on(\"data\",c=>p+=c).on(\"end\",()=>console.log(require(\"/opt/node-red/node_modules/bcryptjs\").hashSync(p,12)))" > /etc/node-red/credentials/admin-hash'
sudo systemctl restart node-redFor the api login, write the hash to /etc/node-red/credentials/api-hash the same way. Node-RED checks it as well as nginx. Update /var/lib/sac/data/node-red-credentials.txt too, so that it does not hold old passwords.
Node-RED limits sign-in attempts. After more than five attempts for one user name within ten minutes, it refuses that user name, even with the right password. The block lasts until the ten minutes have passed or you restart Node-RED (sudo systemctl restart node-red).
Optional features (off by default)
Node-RED's settings are in /etc/node-red/settings.js. Edit the file as root, then run sudo systemctl restart node-red. The configuration reference lists every setting. Secrets are not in that file.
- Palette manager. The palette manager installs extra nodes from the Node-RED library. It is off because npm would download and run packages from the internet as the
node-reduser. To switch it on, setallowInstall: true(andallowUpload: trueto install from a file) in thepalette:line underexternalModules. Remove"*"from itsdenyList, then restart Node-RED. Nodes are installed into/var/lib/node-red/data/node_moduleswith the npm that Node-RED bundles. The image has no C compiler, so nodes that compile native code at install time fail unless you install one (sudo apt-get install -y build-essential). - npm modules in function nodes.
functionExternalModules: falseand themodules:line underexternalModuleskeep function nodes from installing npm modules. Change both to allow it. - Telemetry and the update check are off (
telemetry: { enabled: false, updateNotification: false }). - Public HTTP endpoints. Run
sudo node-red-api-auth off(Step 7). - Projects (
git-backed flows) are off. To turn them on, you need git and outbound access to your git server.
The metadata service stays blocked whatever you switch on.
Check the security posture from the command line
Without the HTTP login, every editor page and API call is refused, including Node-RED's sign-in endpoint and the editor's WebSocket. Port 80 redirects to HTTPS. The health check stays open for load balancers. A request for a host name that the instance does not serve is dropped without an answer:
H=$(sudo grep '^NODE_RED_URL=' /var/lib/sac/data/node-red-credentials.txt | sed -E 's#^NODE_RED_URL=https://([^/]+)/.*#\1#') R="--resolve $H:443:127.0.0.1 --resolve $H:80:127.0.0.1" curl -s -o /dev/null -w 'http:// -> %{http_code} %{redirect_url}\n' $R "http://$H/" curl -sk -o /dev/null -w 'editor, no login -> HTTP %{http_code}\n' $R "https://$H/" curl -sk -o /dev/null -w 'sign in endpoint, no login -> HTTP %{http_code}\n' $R -X POST "https://$H/auth/token" curl -sk -o /dev/null -w 'flows API, no login -> HTTP %{http_code}\n' $R "https://$H/flows" curl -sk --http1.1 -o /dev/null -w 'editor WebSocket, no login -> HTTP %{http_code}\n' $R -H 'Connection: Upgrade' -H 'Upgrade: websocket' -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' "https://$H/comms" curl -sk -w '\n' $R "https://$H/health" curl -sk -o /dev/null -w 'unknown host -> %{http_code}\n' --resolve "evil.example:443:127.0.0.1" "https://evil.example/" || truehttp:// -> 301 https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/ editor, no login -> HTTP 401 sign in endpoint, no login -> HTTP 401 flows API, no login -> HTTP 401 editor WebSocket, no login -> HTTP 401 {"type":"credentials","prompts":[{"id":"username","type":"text","label":"user.username"},{"id":"password","type":"password","label":"user.password"}]} unknown host -> 000000 means that nginx closed the connection without answering. nginx treats any host name it does not serve this way.
With the HTTP login, the editor page loads, but Node-RED's API still requires Node-RED's own sign-in. Requests that arrive from another website are refused. A flow deploy whose browser Origin is another site, or a WebSocket handshake from another site, gets HTTP 403:
sudo bash -c ' F=/var/lib/sac/data/node-red-credentials.txt H=$(grep "^NODE_RED_URL=" $F | sed -E "s#^NODE_RED_URL=https://([^/]+)/.*#\1#") printf "user = \"admin:%s\"\n" "$(grep "^HTTP_PASSWORD=" $F | cut -d= -f2-)" > /run/nr-gate.cfg; chmod 600 /run/nr-gate.cfg c() { curl -K /run/nr-gate.cfg -sk --resolve "$H:443:127.0.0.1" -o /dev/null "$@"; } c -w "editor page with the HTTP login -> HTTP %{http_code}\n" "https://$H/" c -w "flows API with the HTTP login only -> HTTP %{http_code}\n" "https://$H/flows" c -w "flow deploy from another site -> HTTP %{http_code}\n" -X POST -H "Origin: https://evil.example" -H "Content-Type: application/json" --data "[]" "https://$H/flows" c --http1.1 -m 3 -w "editor WebSocket, other origin -> HTTP %{http_code}\n" -H "Origin: https://evil.example" -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" "https://$H/comms" c --http1.1 -m 3 -w "editor WebSocket, same origin -> HTTP %{http_code}\n" -H "Origin: https://$H" -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" "https://$H/comms" || true rm -f /run/nr-gate.cfg 'editor page with the HTTP login -> HTTP 200 flows API with the HTTP login only -> HTTP 401 flow deploy from another site -> HTTP 403 editor WebSocket, other origin -> HTTP 403 editor WebSocket, same origin -> HTTP 101Node-RED answers on 127.0.0.1 only. The certificate was generated on this instance as a server certificate that cannot sign other certificates:
PRIV=$(hostname -I | awk '{print $1}') timeout 3 bash -c "exec 3<>/dev/tcp/$PRIV/1880" 2>/dev/null && echo "1880 open on $PRIV" || echo "1880 closed on $PRIV" openssl x509 -in /etc/ssl/node-red/node-red.crt -noout -subject -ext basicConstraints,keyUsage,extendedKeyUsage,subjectAltName1880 closed on <private-ip> subject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = sac X509v3 Subject Alternative Name: DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost X509v3 Basic Constraints: critical CA:FALSE X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server AuthenticationServer components
Component Path
Node-RED 5.0.9 /opt/node-red (installed from /opt/node-red/package-lock.json)
Node.js 24.22.1 /opt/nodejs/bin/node (node on the PATH; no npm or npx)
Settings /etc/node-red/settings.js
Per instance secrets /etc/node-red/credentials/ (root only: Node-RED admin and api password hashes, flow credential key)
Flows and data /var/lib/node-red (data volume)
Node-RED service node-red.service (user node-red; 127.0.0.1:1880)
Build record, licenses, dependency lock, audit report, checksums /usr/share/doc/sac-node-red/
nginx site /etc/nginx/sites-available/sac-node-red
HTTP login files /etc/nginx/.node-red-htpasswd, /etc/nginx/.node-red-api-htpasswd (bcrypt)
Certificate and key /etc/ssl/node-red/
First boot script /usr/local/sbin/node-red-firstboot.sh
Host name helper /usr/local/sbin/node-red-set-hostname
/api/ login switch /usr/local/sbin/node-red-api-auth
Self test /usr/local/sbin/node-red-selftest
Credentials /var/lib/sac/data/node-red-credentials.txt (mode 0600)
/opt/nodejs/bin/node -p "require('/opt/node-red/node_modules/node-red/package.json').version" node --version command -v gcc npm npx || echo "no C compiler, no npm on the PATH" nginx -v 2>&1 sed -n '/^npm audit gate/p;/^outbound/p' /usr/share/doc/sac-node-red/BUILD-INFO.txt5.0.9 v24.22.1 no C compiler, no npm on the PATH nginx version: nginx/1.24.0 (Ubuntu) npm audit gate OK reviewed-only: ip-address:moderate undici:high outbound telemetry + update check OFF, diagnostics OFF, palette manager OFF, metadata egress blockedSecurity notes and recommendations
- Allow ports 22, 80 and 443 in the security group from your own networks only.
- Anyone with the HTTP and Node-RED passwords can run code on the instance as
node-red, read and change every flow, and use every credential stored in your flows. Share the passwords only with people you would give SSH access, and rotate them (Step 11) if they may have leaked. - Known advisories that do not apply to this image, rechecked at each Node-RED release:
- The editor bundles DOMPurify 3.4.14 (vendor/vendor.js), 3.4.12 (inside mermaid 11.17.2) and 3.4.15 (inside the Monaco code editor). Those versions have published advisories that only apply when the calling code switches on DOMPurify's SAFE_FOR_TEMPLATES option with a DOM output mode, its IN_PLACE option or the application/xhtml+xml parser mode. Nothing in the editor sets any of them, and SecureAnyCloud's build fails if a shipped editor file ever starts to.
- The
npmpackage that Node-RED uses for its palette manager bundles undici 6.29.0 and ip-address 10.7.2. These have published advisories, and no npm release with fixed copies exists yet. npm runs only when the palette manager or function node modules install something, and both are off on this image (Step 12). The build checks that Node-RED refuses those installs. If you switch the palette manager on, npm runs and downloads over HTTPS from the npm registry. - By design, flows can make HTTP requests to any address the instance can reach, including your VPC. The metadata service is the exception. Treat anyone who can deploy flows as able to reach your network from the instance.
- Use your own DNS name and a certificate your clients trust (Step 10).
- Keep the operating system patched. Unattended security upgrades are on, and
sudo apt-get update && sudo apt-get upgradeapplies everything else. New versions of this AMI update Node.js and Node-RED.
Support and licensing
Node-RED is open source under the Apache License 2.0 (OpenJS Foundation). The license text is in /usr/share/doc/sac-node-red/. Node.js is MIT licensed. There is no per-user or per-CPU license fee. The AMI price covers SecureAnyCloud's build, hardening, first-boot setup and support.
- Email: sales@secureanycloud.com
- Website: https://secureanycloud.com
- Support: 24/7, with a 24-hour response SLA
Deploy on AWS
Launch Node-RED 5.0.9 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com