Skip to content

Keep a name on a changing address with Dynamic IP ​

A home line, an office connection or a server behind NAT gets a new public address now and then. Dynamic IP keeps DNS records pointing at it: something reports the current address, and InfraNest updates every record the source keeps, with a history, an alert when the address changes, and a dynamic_ip.changed event your automations and webhooks receive. A source can also keep a firewall rule open to that address only.

Create the source in the app under Automations → Dynamic IPs, attach the records it should keep, and copy its update password. Then report the address one of three ways:

You haveUseCredential
A router, ddclient, a cron jobthe update endpointthe source's own update password
A script on the connection itselfcheck in from your own addressan API token
A script that knows the new addressset the addressan API token

Runnable code: infranest-examples/examples/dynamic-ip, run against the sandbox by CI.

The update endpoint ​

The update endpoint speaks dyndns2, the protocol routers and ddclient already know. It needs no API token: each source has its own update password, which can do this one thing and nothing else.

https://dyn.infranest.io/                  password in HTTP Basic auth (recommended)
https://dyn.infranest.io/<password>        password in the path
https://dyn.infranest.io/nic/update        the dyndns2 path routers append; /v3/update and /update work too

Send the password as the Basic-auth password and the source's public id as the username, so it stays out of shell history, proxy logs and referrers. Without an address in the request, the address the request comes from is used — usually what you want.

ParameterMeaning
myip or ipv4Report this IPv4 address instead of the one the request comes from
myipv6 or ipv6Report this IPv6 address
hostnameAccepted and ignored: the source decides which records it keeps
AnswerStatusMeaning
good 198.51.100.7200The address changed; records and firewalls are being updated
nochg 198.51.100.7200Already this address; nothing to do
badauth401No source has this password. The same answer whether or not the username exists
nohost422Authenticated, but the request carried no usable address

At most 60 requests a minute from one address. A router that calls every few minutes is well inside that.

curl, from cron ​

sh
# Every 5 minutes. The address is the one this request comes from.
# /etc/infranest-dyn.env (chmod 600):  DYN_USER=<public id>  DYN_PASSWORD=<update password>
*/5 * * * * . /etc/infranest-dyn.env && curl -fsS -u "$DYN_USER:$DYN_PASSWORD" https://dyn.infranest.io/ >/dev/null

To report both families from a dual-stack connection, call it once over each:

sh
curl -4 -fsS -u "$DYN_USER:$DYN_PASSWORD" https://dyn.infranest.io/
curl -6 -fsS -u "$DYN_USER:$DYN_PASSWORD" https://dyn.infranest.io/

ddclient ​

protocol=dyndns2
server=dyn.infranest.io
ssl=yes
# login: the source's public id; password: its update password
login=dyn_PUBLIC_ID
password='change-me'
your-hostname.example.com

The last line is required by ddclient and ignored by InfraNest.

A systemd timer ​

ini
# /etc/systemd/system/infranest-dyn.service
[Service]
Type=oneshot
EnvironmentFile=/etc/infranest-dyn.env   # DYN_USER=…  DYN_PASSWORD=…  (chmod 600)
ExecStart=/bin/sh -c 'curl -fsS -u "$DYN_USER:$DYN_PASSWORD" https://dyn.infranest.io/'
ini
# /etc/systemd/system/infranest-dyn.timer
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min

[Install]
WantedBy=timers.target

systemctl enable --now infranest-dyn.timer.

Check in from your own address ​

With an API token instead of the update password — a script that already holds one — check in, and the address the request comes from becomes the source's:

sh
curl -fsS -X POST https://api.infranest.io/api/organizations/42/dynamic-ips/7/check-in \
  -H "Authorization: Bearer $INFRANEST_TOKEN" -H "Accept: application/json"
json
{ "ip": "198.51.100.7", "family": "v4" }

Set the address ​

A script that knows the new address — a deploy step, a cloud hook — sets it:

sh
curl -fsS -X PUT https://api.infranest.io/api/organizations/42/dynamic-ips/7/address \
  -H "Authorization: Bearer $INFRANEST_TOKEN" -H "Accept: application/json" \
  -H "Content-Type: application/json" -d '{"ipv4": "198.51.100.7"}'
json
{ "changed": true, "applied": 1, "current_ipv4": "198.51.100.7", "current_ipv6": null }

ipv4, ipv6 or both. Everything a router check-in does follows: the records, the history, the alert and the event. changed is false when it was already this address.

Token: Monitoring → Write (monitoring.write) — dynamic IPs sit under the Monitoring scope. A token can also attach and detach DNS records, edit the label, alerts and tags, recheck, follow a server's agent, and delete a source; see the reference.

A source that keeps a firewall open

An API token may not change a source that keeps a firewall rule up to date: a new address would change who can reach the server. Those answer 403 not_token_writable. Report their address through the update endpoint — its password is made for exactly this one source — or change them in the app. Creating a source and rotating its update password are app-only too: each makes a credential that outlives your API token.

Which to choose ​

Use the update endpoint for anything that runs on the connection itself, and set the address with a token when something else knows it. Rewriting a DNS record directly, as in Update DNS from a script, also works, but skips the history, the change alert and the firewall.