A Cloudflare Worker that automatically updates DNS records (A/AAAA) when your public IP changes.
Ideal if your ISP does not provide a static IP and you want to keep your self-hosted services reachable with your Cloudflare domain.
- Update multiple DNS records in a single request (root + subdomains).
- Works with any router/NAS that supports custom DDNS providers (Omada, OpenWrt, Fritz!Box, pfSense, Synology, etc.).
- Secure:
- Basic Auth between router and Worker.
- Scoped Cloudflare API Token with minimal permissions (
DNS:Edit
+Zone:Read
).
- DDNS-style responses (
good ip
,nochg ip
) for compatibility and easy debugging.
- Go to Cloudflare API Tokens.
- Create Token → Edit DNS Template.
- Permissions:
Zone → Zone → Read
Zone → DNS → Edit
- Scope: restrict to your zone (e.g.,
example.com
). - Save the token → this is your
CF_API_TOKEN
.
- Zone ID: available in the Cloudflare Dashboard, Overview tab of your domain.
- Save the Zone ID → this is your
CF_ZONE_ID
.
- Record IDs: list them with
curl
+jq
:curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?per_page=100" \ -H "Authorization: Bearer $CF_API_TOKEN" \ -H "Content-Type: application/json" \ | jq '.result[] | {id, type, name, content}'
- Save the record IDs of your domains, you will need them to complete the
worker.js
file.
- Go to Workers & Pages → Create Worker → Start from “Hello World”.
- Deploy the code as-is.
- Open the code editor, remove the “Hello World” snippet, and paste the content of
worker.js
. - Complete the
const RECORDS = {};
section with your domains and record IDs. - In Settings → Variables and Secrets add:
CF_API_TOKEN
(Secret)CF_ZONE_ID
(Text)BASIC_USER
(Text)BASIC_PASS
(Secret, strong password recommended)
- Settings → Domains & Routes → Add Custom Domain
- Example:
ddns.example.com
- Your endpoint will be:
https://ddns.example.com/update?hostname=example.com
Use the Worker as a custom DDNS provider.
Example URL:
https://[USERNAME]:[PASSWORD]@ddns.example.com/update?hostname=[DOMAIN]
Where [DOMAIN]
is the DNS record you want to update (e.g. dns1.example.com
).
It is also possible to update all records together: in that case, configure hostname=example.com
(the root domain) and the Worker will update all records defined in its map.
curl -u USER:PASS "https://ddns.example.com/update?hostname=dns1.example.com&ip=203.0.113.42"
Expected output:
good 203.0.113.42
→ IP updatednochg 203.0.113.42
→ IP unchanged
curl -u USER:PASS "https://ddns.example.com/update?hostname=example.com&ip=203.0.113.42&verbose=1"
Expected output (example):
good 203.0.113.42
example.com -> good
www.example.com -> good
dns1.example.com -> good
dns2.example.com -> good
MIT — free to use, modify and share.