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 have | Use | Credential |
|---|---|---|
A router, ddclient, a cron job | the update endpoint | the source's own update password |
| A script on the connection itself | check in from your own address | an API token |
| A script that knows the new address | set the address | an 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 tooSend 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.
| Parameter | Meaning |
|---|---|
myip or ipv4 | Report this IPv4 address instead of the one the request comes from |
myipv6 or ipv6 | Report this IPv6 address |
hostname | Accepted and ignored: the source decides which records it keeps |
| Answer | Status | Meaning |
|---|---|---|
good 198.51.100.7 | 200 | The address changed; records and firewalls are being updated |
nochg 198.51.100.7 | 200 | Already this address; nothing to do |
badauth | 401 | No source has this password. The same answer whether or not the username exists |
nohost | 422 | Authenticated, 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
# 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/nullTo report both families from a dual-stack connection, call it once over each:
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.comThe last line is required by ddclient and ignored by InfraNest.
A systemd timer
# /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/'# /etc/systemd/system/infranest-dyn.timer
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
[Install]
WantedBy=timers.targetsystemctl 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:
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"{ "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:
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"}'{ "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.