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 composeon. 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
Settingstab. 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 bashto get a shell inside the runningnode-redcontainer - 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-redcontainer’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
Securitytab - Scoll down to the
Long Lived Access TokensSection 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
Palettetab from the dialog’s left side, thenInstallon 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
APInode, and drag it onto the Flow palette. - Double-click the new node. An
Edit API nodedialog 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
Doneto save. It’ll switch to the properties tab, just clickDoneagain. - You’ll now see a
Deploybutton 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 Statenode onto your flow palette. - Double-click it to edit it
- You should see your Home Assitant connection is already selected in the
Serverentry - Start typing an entity name in the
Entity IDfield. 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.