Node-RED Setup
Relevant source files
The following files were used as context for generating this wiki page:Node-RED serves as the orchestration and logic layer within the Overlord Network Kill Switch project. Its primary role is to act as a bridge between the MQTT message broker and the backend Gunicorn/Flask web server. It subscribes to specific MQTT topics published by HomeKit (via homebridge-mqttthing), parses these messages, and translates them into HTTP requests to the appropriate API endpoints on the web server to control Pi-hole and Ubiquiti services.
The design philosophy is to keep Node-RED focused on transport rather than heavy-lifting configuration management, which is handled by the backend server. The provided dns.json flow file contains all the necessary logic for this translation process.
Sources: README.md:1-10, 24, node_red_flows/dns.json
Architecture and Core Components
The Node-RED flow is designed around three main control paths: Pi-hole media/domain blocking, Pi-hole master enable/disable, and Ubiquiti router control. It uses a central MQTT broker and a configured web server endpoint.
Sources: README.md:92-116, node_red_flows/dns.json
MQTT Broker Configuration
All mqtt in and mqtt out nodes are configured to connect to a central MQTT broker. In the example flow, this is named "The Mothership" and connects to 192.168.100.104:1883.
Sources: node_red_flows/dns.json:422-446
Web Server Endpoint
The flows rely on a flow-level context variable endpoint which stores the base URL of the backend web server. In the provided example, this is hardcoded to http://XXXX:19000 and must be updated to the correct IP address of the machine running the Gunicorn server.
{
"t": "set",
"p": "endpoint",
"pt": "flow",
"to": "http://XXXX:19000",
"tot": "str"
}
Sources: node_red_flows/dns.json:310-315
Pi-hole Media Control Flow
This flow manages the enabling and disabling of specific domain block groups (e.g., hbomax, school_work) on Pi-hole.
Sources: node_red_flows/dns.json:10-103
Data Flow
The following diagram illustrates how a command from HomeKit is processed to change a Pi-hole domain block.
MQTT Topics
| Action | Topic | Payload | Description |
|---|---|---|---|
| Command | cmnd/dns_controller/media/+/change | true / false | Sent from HomeKit to enable/disable a domain block group. The + is a wildcard for the group name (e.g., hbomax). |
| Status | stat/dns_controller/media/+/status | true / false | Published by Node-RED to update the status of the switch in HomeKit. |
Sources: node_red_flows/dns.json:15-20, 75-80, README.md:52-62
Logic Processing
An mqtt in node listens for changes. The message topic is parsed by a "Common Parsing" change node to extract the target (e.g., hbomax) and verb (change). A function node then constructs the appropriate HTTP request for the web server.
- If the payload is
true, the verb becomesenable. - If the payload is
false, the verb becomesdisable. - The final URL is constructed as:
${webserver}/pihole/${verb}/${target}.
// From function node 'f2bf547fc050a016'
let webserver = flow.get('endpoint');
// ... validation ...
msg.topic = `stat/dns_controller/media/${msg.target}/status`
msg.url = `${webserver}/pihole/${msg.verb}/${msg.target}`
if (msg.verb == "status"){
msg.method = "GET"
}
else if (msg.verb == "change")
{
msg.method = "POST"
if (msg.payload == "true") msg.verb = "enable"
if (msg.payload == "false") msg.verb = "disable"
msg.url = `${webserver}/pihole/${msg.verb}/${msg.target}`
}
return msg;
Sources: node_red_flows/dns.json:58-86
Pi-hole Master Control Flow
This flow manages the global enabling and disabling of DNS blocking across all configured Pi-hole instances. It can handle both permanent and temporary changes.
Sources: node_red_flows/dns.json:104-205
Data Flow
This diagram shows the process for globally disabling DNS blocking.
MQTT Topics
| Action | Topic | Payload | Description |
|---|---|---|---|
| Command | cmnd/dns_controller/master/+ | true / false | Sent from HomeKit to change the master DNS state. The wildcard can be perm_change or short_change. |
| Status | stat/dns_controller/master/status | true / false | Published by Node-RED to update the master switch status in HomeKit. |
Sources: node_red_flows/dns.json:109-114, 160-165, README.md:63-71
Logic Processing
The logic differentiates between permanent and temporary changes based on the MQTT topic.
- A topic including
short_changeadds a?timer=300query parameter to the request, telling the API to disable blocking for 300 seconds. - A payload of
true(turn OFF blocking) maps to aPOSTrequest. - A payload of
false(turn ON blocking) maps to aDELETErequest. - The URL is
${webserver}/alldns/with an optional timer.
// From function node '53d8609db4b811ee'
let webserver = flow.get('endpoint');
// ...
let jl = msg.topic.split('/')
let disable_type = jl[3]
// ...
var method =""
let intent = msg.payload
let timer = null;
if (jl[2]=='short_change') timer = 300;
if (intent == "true"){
msg.method = "POST";
method="disable";
}
if (intent == "false") {
msg.method = "DELETE"
method="enable";
}
// ...
let temp = ''
if (timer != null) temp = `?timer=${timer}`
msg.url = `${webserver}/alldns/${temp}`
Sources: node_red_flows/dns.json:141-159
Ubiquiti Router Control Flow
This flow manages Ubiquiti firewall rules, allowing them to be enabled or disabled via MQTT messages.
Sources: node_red_flows/dns.json:206-335
Data Flow
MQTT Topics
| Action | Topic | Description |
|---|---|---|
| Command | cmnd/router_controller/change_rule/+ | Enables/disables a firewall rule. The + is the rule name. |
| Status | stat/router_controller/status_rule/+ | Publishes the current status of the firewall rule. |
Sources: node_red_flows/dns.json:211-216, 287-292
Logic Processing
A "Common Parsing" node first extracts the target (rule name) and verb (e.g., change_rule) from the topic. A function node then maps the verb and payload to a specific API endpoint path.
verb: change_rule,payload: false->disable_ruleverb: change_rule,payload: true->enable_rule- The final URL is constructed as:
${webserver}/ubiquiti/${router_path}/${msg.target}.
The flow also includes logic for device-level blocking (change_device) and status checks (status_rule, status_device). After a successful API call, a 1-second delay node is used before the status is published back to MQTT.