Nodered, Home Assistant and Tailscale
I’m moving my Home Assistant from a docker container to a proxmox VM running HAOS, and as part of that I’m moving Node-RED to its own container so I can move it to other proxmox hosts independently of HAOS.
I’m setting up a new Node-RED instance as part of moving Home Assistant out of docker and onto an HAOS VM. My requirements were:
- Run Node-RED in a separate VM so I can move it to other proxmox hosts if there is resource contention or I need to fail over
- Proper SSL certificate
- Easy access via my tailnet
Pre-requisites
To follow these instructions, you will need:
- Your own Tailnet. You can get a free tailnet at Tailscale.com.
- A server with docker installed that you can run
docker compose
on. I’m using a LXC container in my proxmox cluster, but you can run it on a standalone linux server. - A working Home Assistant server.
Installation
Installing docker and Home Assistant are out of scope for this post. We will only be covering how to get Node-RED working with an existing Home Assistant server.
Get a Tailscale Auth key
- Log into the Tailscale admin page.
- Click the
Settings
tab. On the bottom left, you’ll see aPersonal Settings
, and under that,Keys
. - Click
Generate Auth Key
. - Give it a description, and then click
Generate Key
- Copy the key to someplace secure, it won’t be displayed again
Create a configuration file for tailscale serve
By default, node-red
runs on port 1880. Because we’re running tailscale
and node-red
in the same docker network, the tailscale
container will be able to connect to port 1880 on the node-red
container and act as a proxy.
Save this as ts-config/nodered.json
.
{
"TCP": {
"443": {
"HTTPS": true
}
},
"Web": {
"${TS_CERT_DOMAIN}:443": {
"Handlers": {
"/": {
"Proxy": "http://127.0.0.1:1880"
}
}
}
},
"AllowFunnel": {
"${TS_CERT_DOMAIN}:443": false
}
}
Docker Compose
Now that we have an auth token and a configuration file for tailscale, we’re going to use docker compose
to start up node-red
and a ts-nodered
containers. The ts-nodered
sidecar will connect to tailscale, register itself as nodered.your-tailnet.ts.net
, use Lets Encrypt to create a SSL certificate that is trusted by your browser, then finally start proxying SSL traffic from nodered.your-tailnet.ts.net
into the node-red
container.
This docker-compose file is based on the Node-RED Getting Started with Docker page. I added a ts-nodered
container to act as a tailscale sidecar and made some other minor changes. I prefer to mount a local directory instead of using a docker volume to make backups easier. I can copy the directory into a .tar.bz2
or .zip
file, and it’s also easier to edit the configuration files since I can do that from the host OS.
Save this as docker-compose.yaml
################################################################################
# Node-RED Stack or Compose
################################################################################
version: "3.7"
services:
ts-nodered:
image: tailscale/tailscale:latest
# The hostname specified here will be registered in your tailnet. You will
# be able to access Node-RED by entering nodered.your-tailnet.ts.net into
# your browser
hostname: nodered
environment:
# Set TS_AUTHKEY in the environment, you don't want it saved in
# cleartext here
- TS_AUTHKEY=${TS_AUTHKEY}
- TS_STATE_DIR=/var/lib/tailscale
- TS_SERVE_CONFIG=/config/nodered.json
- TS_USERSPACE=true
volumes:
- ./ts-config:/config
- ./ts-state:/var/lib/tailscale
restart: unless-stopped
nodered:
container_name: node-red
image: nodered/node-red:latest-debian
# If you don't set the network_mode to the name of the tailscale sidecar
# container, tailscale won't be able to connect to Node-RED and you will
# have 500 errors
network_mode: service:ts-nodered
restart: unless-stopped
environment:
- TZ=America/Denver
# We specify the port in nodered.json so tailscale serve knows what port to
# proxy to. We don't actually activate external access to these ports since
# everything gets proxied by Tailscale.
#
# ports:
# - "1880:1880"
volumes:
- ./nodered:/data
- ./externals:/externals
- /etc/hostname:/etc/hostname:ro
- /etc/localtime:/etc/localtime:ro
- /etc/machine-id:/etc/machine-id:ro
- /etc/timezone:/etc/timezone:ro
Start Node-RED
Prepare Your Node-RED Directory
First, prepare your directory. You need to make a few subdirectories and move tailscale’s configuration file into the ts-config
subdirectory.
mkdir ts-config && mkdir ts-state
Move the nodered.json
file into the ts-config
directory. Your directory structure should look like this:
./docker-compose.yaml
./ts-config/nodered.json
./ts-state
Start the Node-RED containers
We’re going to pass the Tailscale auth token as an environment variable so we don’t have it visible in the configuration file. Run docker compose
using the command below
export TS_AUTHKEY='yourReallyLongTailscaleAuthKey'
docker compose up -d ; docker compose logs -f
In a minute or two depending on your network connection, you’ll see a bunch of logs start scrolling. Eventually you should see a line like:
ts-nodered-1 | 2025/07/14 00:54:52 serve: creating a new proxy handler for http://127.0.0.1:1880
to show that the ts-nodered
proxy is up and running, and another line similar to
node-red | 13 Jul 18:54:52 - [info] Server now running at http://127.0.0.1:1880/
when the node-red container is ready. The containers start in parallel, so the order of those lines isn’t guaranteed. Once you’ve seen both lines, you can go to nodered.your-tailnet.ts.net
in your browser and access the Node-RED web interface. The first time you do this, it’ll take a little longer while tailscale generates a SSL certificate for the host with Lets Encrypt.
There’s one last thing to do before we can consider this operational.
Make Node-RED require a login
Create your password hash
- Run
docker exec -it node-red bash
to get a shell inside the runningnode-red
container - Run
node-red admin hash-pw
. It will ask you for a password that will be used to log into yournode-red
, then print out a hash. Save that so we can update thenode-red
container’s configuration.
Update settings.js
Use your editor of choice to edit ./nodered/settings.js
. You will find a commented out block that looks like
//adminAuth: {
// type: "credentials",
// users: [{
// username: "admin",
// password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.",
// permissions: "*"
// }]
//},
Replace that with:
adminAuth: {
type: "credentials",
users: [{
username: "admin",
password: "TheHashFromRunning_nNodered_admin_hash-pw",
permissions: "*"
}]
},
Now we restart Node Red so it picks up the new admin
user you created.
docker compose restart
Give it 15-30 seconds, then refresh your browser. It should now give you a login dialog and make you login as admin
with the password you input to the node-red admin hash-pw
command.
Connecting Node-RED to Home Assistant
Now that you have a running Node-RED instance, you need to connect it to your Home Assistant server.
Create an access token
To connect Node-RED to your Home Assistant (HA), we’re going to need an access token. To create an access token:
- Log into your HA instance
- Click on your username at the bottom of the sidebar
- Select the
Security
tab - Scoll down to the
Long Lived Access Tokens
Section and clickCeate Troken
. - Name the new token. Store it someplace safe, it will only be displayed once.
Configure the connection between Node-RED and Home Assistant
- Log into your Node-RED instance
- Click the burger menu on the right side of the screen, and select
Manage Palette
- Select the
Palette
tab from the dialog’s left side, thenInstall
on the top - Install the HA plugin. Make sure you pick the one named
node-red-contrib-home-assistant-websocket
. You do not want the one namednode-red-contrib-home-assistant
, it is old and abandoned. You will now see a bunch more HA-related nodes in the left sidebar. - Scroll down, find the
API
node, and drag it onto the Flow palette. - Double-click the new node. An
Edit API node
dialog will appear, click add new server. Keep the protocol as Websocket. Do not check theUsing the Home Assistant Add-on
, we’re running Node-RED outside the HAOS instance. Put in the DNS name or IP address of your Home Assistant server. - Hit
Done
to save. It’ll switch to the properties tab, just clickDone
again. - You’ll now see a
Deploy
button at the upper right of the screen. Click that so NR can activate the connection to your HA instance
You should be good to start writing Node-RED automations for your Home Assistant, but let’s verify that it’s working.
Verifying your Node-RED connection
- Drag a
Current State
node onto your flow palette. - Double-click it to edit it
- You should see your Home Assitant connection is already selected in the
Server
entry - Start typing an entity name in the
Entity ID
field. If things are working correctly, it will start auto-completing the name for you.
If it autocompleted, you’re good to go. Creating automations in NR is out of scope for this post, but there are a ton of videos on YouTube to show you how.
Congratulations, you now have Node-RED running independently from Home Assistant.