cf-ddns

View script Copied!

Update a Cloudflare DNS A record to match this machine's current outbound IP address – a lightweight dynamic DNS solution for home servers, dev machines, or any host behind a changing IP.

Designed to run periodically from the target host (via cron or systemd timer). Fetches the machine's public IP from ipify.org, compares it to the hostname's current DNS resolution via Google DNS, and updates Cloudflare only when they differ. The hostname can be a zone apex such as example.com or a name within that zone such as home.example.com.

Quick start

$ cf-ddns YOUR_API_TOKEN home.example.com
[INF][cf-ddns] Device's IP: 203.0.113.42
[INF][cf-ddns] Hostname's IP: 198.51.100.8 (home.example.com)
[INF][cf-ddns] IP addresses do not match, updating DNS
[INF][cf-ddns] Deleting A record for 198.51.100.8 (abc123...)
[INF][cf-ddns] Creating A record for 203.0.113.42

For home.example.com, the script selects the example.com zone and replaces only A records named home.example.com. A records for the zone apex and other hostnames are left alone. TTL is hardcoded to 60 seconds for fast propagation.

Create a Cloudflare API token:

  1. Go to the Cloudflare dashboard > API Tokens
  2. Create token with permissions: Zone.Zone (read) and Zone.DNS (edit)
  3. Scope to the specific zone if desired

Common examples

Run from cron every 5 minutes:

# crontab entry
*/5 * * * * /path/to/cf-ddns YOUR_API_TOKEN home.example.com 2>&1 | logger -t cf-ddns

Enable debug output to see full curl logs and API call details:

$ DDNS_DEBUG=1 cf-ddns YOUR_API_TOKEN home.example.com
[DBG][cf-ddns] curl output logged to: /tmp/curl.12345.log
[DBG][cf-ddns] GET /zones
[INF][cf-ddns] Device's IP: 203.0.113.42
...

Pipe from the web (since this is published at toolio.sh):

curl -s https://toolio.sh/cf-ddns | bash -s -- YOUR_API_TOKEN home.example.com

How it works

  1. Fetch the machine's outbound IP via curl https://api.ipify.org
  2. Query the hostname's current A record via dig @8.8.8.8 +tcp +short $hostname (Google DNS, TCP mode to avoid UDP blocks)
  3. Compare IPs – if they match, exit early with success
  4. If they differ:

Replacing all A records for the requested hostname ensures a clean state even if multiple records exist from manual edits or migrations.


Reference

All options

Flag Description
-h, --help Show help message with synopsis, description, dependencies, and API token requirements

Arguments

Argument Description
api_token Cloudflare API token (required permissions: Zone.Zone, Zone.DNS)
hostname Fully qualified DNS hostname to update (e.g. home.example.com)

Environment variables

Variable Description
DDNS_DEBUG Set to any value to enable verbose curl and debug output. Logs API calls and curl traces to stderr.

Exit codes

Code Meaning
0 Success (IP already matched or DNS updated successfully)
1 Runtime failure (IP fetch failed, zone not found, API error)
2 Usage error (missing API token or hostname)
3 Dependency error (curl, jq, or dig missing)

Dependencies

Warnings

Behavior