Wheelhouse docs

Dynamic DNS#

The second tab of DNS, at /dns. It owns service dns dynamic.

A provider that gives you a different address every few weeks makes a fixed name impossible — unless something tells the DNS provider each time it changes. That something is a dynamic DNS client, and on this base it is ddclient, configured through the configuration tree like everything else.

Where the data comes from#

GET /api/ddns, polled every 60 seconds, returns four things — agent/opmode.go (handleDDNS):

json
{
  "config": { "name": { "home": { "protocol": "cloudflare", "…": "" } } },
  "status": [],
  "configured": true,
  "raw": "…"
}

config is the service dns dynamic subtree, status is show dns dynamic status parsed into rows, and configured is deliberately careful: it is true when the configuration subtree exists, or when the status read succeeded, had content, and did not contain the words not configured. A failed status read no longer counts as configured, and neither does an empty status table.

Two configuration layouts#

VyOS has changed the shape of this subtree. The page reads both.

The current layout is one entry per service, named by you:

service dns dynamic name <label> …

The older layout hangs services off an interface:

service dns dynamic address <interface> service <name> …

Entries in the old layout are shown in their own panels, labelled older address … service layout, read-only apart from what the CLI can do to them. Everything the editor writes uses the current layout.

What each service shows#

FieldNodeWhen unset
Host nameshost-name
Address fromaddress interface <if>, or address web with its optional urlnot set
Zonezone
Usernameusername
Passwordpasswordshown as set or , never the value
Serverserverprovider default
IP versionip-versionipv4
TTLttlprovider default

Delete on a panel stages:

delete service dns dynamic name home

Last update#

Below the services, show dns dynamic status as a table, with whatever columns the router printed. When it is empty the page says so in one line and explains the timing: The client runs every few minutes and on address changes. An empty status table immediately after a commit is normal.

The editor#

+ Add dynamic DNS requires a name, a protocol and at least one host name. Everything else is optional.

FieldCommandNotes
Namethe tag under … dynamic nameyour label. Non-alphanumeric characters other than - and _ are stripped as you type
Provider protocol… protocol <p>a menu of 37 values, as ddclient names them
Host names… host-name <h> per namecomma or space separated
Address to publish… address interface <if> or … address websee below
Lookup URL… address web url <url>only with the web option; ddclient's default otherwise
Zone… zone <z>the root domain; some providers require it
IP version… ip-version ipv6 or … ip-version boththe menu's first entry is ipv4 (default) and writes nothing
Username… username <u>or the token's name, per provider
Password / API token… password <p>stored in the router configuration
Server… server <s>the provider's default otherwise

A complete entry:

set service dns dynamic name home protocol cloudflare
set service dns dynamic name home address interface eth1
set service dns dynamic name home host-name router.example.com
set service dns dynamic name home zone example.com
set service dns dynamic name home username <user>
set service dns dynamic name home password <token>

The two ways to learn the address#

The address on an interface reads the address the router holds. It is right when the router's uplink has the public address — a DHCP or PPPoE uplink from the provider.

What a web lookup sees asks an external service what address your traffic appears to come from. It is right when the router is behind something else that does NAT — a provider's modem in router mode, a carrier-grade NAT. Without a URL, ddclient's own default lookup service is used; with one, that URL is queried instead.

Picking the interface option behind another NAT publishes a private address, and the name resolves to something nobody can reach. That is the commonest failure of this feature and nothing on the page detects it.

The 37 provider protocols#

The menu is the list ddclient supports as the router's own completion presents it — cloudflare, dyndns2, duckdns, noip, freedns, godaddy, namecheap, porkbun, hetzner, digitalocean, gandi, ovh, he.net, nsupdate, zoneedit1, easydns, dnsmadeeasy, changeip, infomaniak, inwx, njalla, nfsn, yandex, regfishde, sitelutions, mythicdyn, keysystems, enom, dondominio, domeneshop, dinahosting, ddns.fm, dnsexit2, dslreports1, dyndns1, freemyip, 1984.

The value is written into the command verbatim. If the running base supports a protocol that is not in this menu, the CLI takes it and this page will display it — ui/src/pages/Dns.tsx.

The password is in the configuration#

It has to be: ddclient needs it to authenticate, and the router's configuration is where VyOS keeps service credentials. Two consequences are worth knowing exactly.

In the configuration reads, it is redacted. password is one of the secret leaf names, and GET /api/config, GET /api/config/commands and the history diff are wrapped in redactSecrets(RoleAdmin, …), so a viewer or an operator sees a blanked value there — agent/security.go.

Use a provider token scoped to the one zone it needs, never an account password, and rotate it if the router's read plane has been shared more widely than you would share the token.

What this tab will not do#

  • No editing an existing service. Delete it and add it again, or use the CLI.
  • No test or force-update button. The client runs on its own schedule; the status table is the only feedback.
  • No entry for the older address … service layout. Those are displayed and not edited.
  • No IPv6-only convenience. The IP version field exists; nothing else on the page is v6-aware.

What breaks if you get it wrong#

  • The wrong interface. Publishing a LAN address, or the address of the uplink that is currently the backup. Pick the interface that actually holds the public address — the Uplinks table shows which one that is.
  • Behind carrier-grade NAT with the interface option. Publishes an unreachable address. Use the web lookup.
  • A missing zone. Several providers reject an update without it, and the error only appears in the router's journal.
  • A token without permission on the zone. Same: silent failure, visible only in the journal.
  • Expecting it to be quick. The client runs every few minutes and on address changes, and the record then has to expire out of caches. A short TTL at the provider is the other half of making a dynamic name useful.

See also#

  • DNS — the resolver tab, and the note about the other tabs being unreachable without a forwarder.
  • Uplinks (multi-WAN) — which interface holds the public address.
  • Addressing — what dhcp and PPPoE do to that address.
  • Logs — where a failed update reports itself.

Checked against ui/src/pages/Dns.tsx, agent/opmode.go (handleDDNS, handleDNS), agent/main.go (routes), agent/security.go, ui/src/lib/api.ts.

Updated 2026-09-02 manual network dns dynamic-dns ddclient