Update DNS from a script when your IP changes
Keep a record such as home.example.com pointing at a connection whose address changes. A small script finds your current address and changes the record only when it differs.
Using a router?
Most routers can update DNS themselves. InfraNest has a built-in Dynamic IP feature for that, with a link your router calls. See Dynamic IP on your router. Use this recipe when you want a script, for example on a Raspberry Pi or in a container.
Runnable code: the code on this page, ready to clone and run, is in infranest-examples/examples/dynamic-dns. CI runs it against the sandbox.
The token
Make a token with DNS → Write only, in the organization that holds the zone.
Find the zone and the record
curl https://api.infranest.io/api/organizations/42/dns-zones \
-H "Authorization: Bearer $INFRANEST_TOKEN" -H "Accept: application/json"Note the zone's id, then list its A records:
curl "https://api.infranest.io/api/organizations/42/dns-zones/318/dns-records?type=A" \
-H "Authorization: Bearer $INFRANEST_TOKEN" -H "Accept: application/json"Note the id of the record you want to keep up to date.
The script
#!/bin/sh
# Updates one A record to this machine's public IPv4 address, only when it changed.
set -eu
API=https://api.infranest.io/api/organizations/42/dns-zones/318/dns-records/9021
current=$(curl -fsS https://api.ipify.org)
stored=$(curl -fsS "$API" -H "Authorization: Bearer $INFRANEST_TOKEN" -H "Accept: application/json" | jq -r .value)
if [ "$current" != "$stored" ]; then
curl -fsS -X PUT "$API" \
-H "Authorization: Bearer $INFRANEST_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"value\":\"$current\",\"ttl\":300}" > /dev/null
echo "Updated to $current"
fiRun it every five minutes, for example with cron: */5 * * * * /usr/local/bin/update-dns.sh.
- A short TTL (300 seconds here) makes the new address take effect quickly. The minimum is 60.
- Only changed addresses are sent, so the script stays well inside the rate limits and the zone's history shows real changes only.
- To see what would change first, add
?dry_run=1to thePUT. See Retries and dry runs.