DuckDNS Update Flow

Purpose

This flow ensures that your DuckDNS domain always resolves to your current public IP address by checking your IP and updating the DuckDNS record if necessary. It is designed for environments with dynamic IPs.

Step-by-Step Flow

Trigger (Inject Node)

Starts the process either manually or on a defined schedule.

Get Public IP (HTTP Request → JSON → Function: extract new ip)

Calls https://api.ipify.org?format=json.

Extracts your current public IP and assigns it to msg.newip.

Get Current DNS IP (HTTP Request: DNS Resolve → Function: extract current ip)

Queries Google DNS at https://dns.google/resolve?name=.duckdns.org&type=A.

Extracts the currently resolved DNS IP and saves it as msg.currentip.

Compare Current vs New IP (Function: compare ip)

If msg.newip !== msg.currentip, it triggers the "update path".

If they are identical, it takes the "no update path".

Prepare DuckDNS Update Parameters (Function: create param)

Prepares:
  • msg.domains = ""

  • msg.token = ""

  • msg.ip = msg.newip

Update DuckDNS (HTTP Request: SET NEW IP)

Calls https://www.duckdns.org/update?domains=&token=&ip=

Ensures DuckDNS resolves your domain to the current public IP.

Error Handling (Catch + Delay)

If DNS query fails, waits 5 seconds and retries.

Key Features

  • Public IP Detection via api.ipify.org.

  • DNS Resolution Check via Google’s DNS API.

  • IP Comparison logic to avoid unnecessary calls to DuckDNS API.

  • Automatic Update of DuckDNS if public IP changes.

  • Retry Mechanism for DNS resolution failures.

[{"id":"2b31cc060817cac7","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"83ebda44e4c5baaa","type":"http request","z":"2b31cc060817cac7","name":"GET IP","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://api.ipify.org?format=json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":260,"y":60,"wires":[["4cf4b3ae7b176ee1"]]},{"id":"7227f64e7625d661","type":"inject","z":"2b31cc060817cac7","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":180,"wires":[["83ebda44e4c5baaa"]]},{"id":"4cf4b3ae7b176ee1","type":"json","z":"2b31cc060817cac7","name":"ip","property":"payload","action":"","pretty":false,"x":390,"y":60,"wires":[["6bbf5e0e1eefdc7e"]]},{"id":"3401fd821db1144e","type":"debug","z":"2b31cc060817cac7","name":"debug2 ip json","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":820,"y":360,"wires":[]},{"id":"469f416c5be7521a","type":"http request","z":"2b31cc060817cac7","name":"SET NEW IP ","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://www.duckdns.org/update?domains={{domains}}&token={{token}}&ip={{ip}}&verbose=true","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1250,"y":220,"wires":[["3d152fdd54fda4fc"]]},{"id":"7879cd4078c25875","type":"function","z":"2b31cc060817cac7","name":"create param","func":"msg.domains = \"<YOUR_DOMAIN>\";\nmsg.token = \"<YOUR_TOKEN>\";\nmsg.ip = msg.newip;\nmsg.verbose = \"true\";\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":970,"y":240,"wires":[["c9cba7641368500d","469f416c5be7521a"]]},{"id":"c9cba7641368500d","type":"debug","z":"2b31cc060817cac7","name":"debug create param","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1240,"y":140,"wires":[]},{"id":"3d152fdd54fda4fc","type":"debug","z":"2b31cc060817cac7","name":"debug set newip","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1300,"y":360,"wires":[]},{"id":"8747b43fc7624ae6","type":"http request","z":"2b31cc060817cac7","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://dns.google/resolve?name=<YOUR_DOMAIN>.duckdns.org&type=A","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":270,"y":280,"wires":[["a7f472d2e4906fc4"]]},{"id":"191e4d421391779f","type":"debug","z":"2b31cc060817cac7","name":"debug ip json","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"newip","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":40,"wires":[]},{"id":"a7f472d2e4906fc4","type":"function","z":"2b31cc060817cac7","name":"extract current ip","func":"msg.payload = JSON.parse(msg.payload);\nmsg.currentip = msg.payload.Answer[0].data;\nmsg.topic = \"currentip\";\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":280,"wires":[["062d88382cbba27b","3401fd821db1144e"]]},{"id":"6bbf5e0e1eefdc7e","type":"function","z":"2b31cc060817cac7","name":"extract new ip","func":"msg.newip = msg.payload.ip;\nmsg.topic = \"newip\";\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":60,"wires":[["191e4d421391779f","8747b43fc7624ae6"]]},{"id":"062d88382cbba27b","type":"function","z":"2b31cc060817cac7","name":"compare ip","func":"if (msg.newip !== msg.currentip) {\n    msg.payload= \"update\";\n    return [msg, null];\n} else {\n    msg.payload= \"no update\";\n    return [null, msg];\n}","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":750,"y":240,"wires":[["7879cd4078c25875","509a1e7f94cbc044"],["03dcd2bcd3d09c64"]]},{"id":"03dcd2bcd3d09c64","type":"debug","z":"2b31cc060817cac7","name":"debug cip false","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1060,"y":360,"wires":[]},{"id":"509a1e7f94cbc044","type":"debug","z":"2b31cc060817cac7","name":"debug cip true","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":980,"y":120,"wires":[]},{"id":"29f044f7eeef9485","type":"catch","z":"2b31cc060817cac7","name":"","scope":["8747b43fc7624ae6","a7f472d2e4906fc4"],"uncaught":false,"x":430,"y":400,"wires":[["9bbb587e32913132"]]},{"id":"9bbb587e32913132","type":"delay","z":"2b31cc060817cac7","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":240,"y":340,"wires":[["8747b43fc7624ae6"]]}]

Flow Info

Created 8 months, 2 weeks ago
Rating: 5 1

Owner

Actions

Rate:

Node Types

Core
  • catch (x1)
  • debug (x6)
  • delay (x1)
  • function (x4)
  • http request (x3)
  • inject (x1)
  • json (x1)
Other
  • tab (x1)

Tags

  • ddns
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option