Update Cloudflare DNS A and AAAA records from your current external IP addresses
Project description
cloudflare-dns-updater
Update Cloudflare DNS A and AAAA records when your external IP address changes.
Published on PyPI as cloudflare-dns-updater.
Install with pipx (recommended)
pipx installs the CLI in an isolated environment and puts cloudflare-dns-updater on your PATH (usually ~/.local/bin).
# install pipx once (Debian/Ubuntu example)
sudo apt install pipx
pipx ensurepath
# open a new shell, or: source ~/.bashrc
pipx install cloudflare-dns-updater
cloudflare-dns-updater --help
Upgrade or reinstall later:
pipx upgrade cloudflare-dns-updater
# or pin a version:
pipx install cloudflare-dns-updater==0.1.0 --force
Other installers:
uv tool install cloudflare-dns-updater
pip install --user cloudflare-dns-updater # not isolated; prefer pipx
Quick start
mkdir -p ~/.config/cloudflare-dns-updater
curl -fsSL https://raw.githubusercontent.com/the-hcma/cloudflare-dns-updater/main/config.example.json \
-o ~/.config/cloudflare-dns-updater/config.json
# edit config.json — set cloudflare_api_token, zone, and dns_entries
cloudflare-dns-updater -v -d # dry-run: discover IPs, no Cloudflare writes
cloudflare-dns-updater # update DNS when IPv4 or IPv6 changed
Create a Cloudflare API token at https://dash.cloudflare.com/profile/api-tokens with permission to edit DNS records for your zone.
Run on a schedule (cron)
After pipx install and config are in place:
# every 5 minutes
*/5 * * * * /home/you/.local/bin/cloudflare-dns-updater >>/tmp/cloudflare-dns-updater.log 2>&1
Use -f if you want to recheck Cloudflare even when local state files show no change.
Configuration
Settings live in config.json. Search order:
-c/--configpathCLOUDFLARE_DNS_UPDATER_CONFIGenvironment variable./config.jsonin the current working directory~/.config/cloudflare-dns-updater/config.json
Copy from config.example.json:
{
"cloudflare_api_token": "your-cloudflare-api-token",
"zone": "example.com",
"dns_entries": ["example.com", "home.example.com"],
"record_ttl": 120,
"ipv6_enabled": true
}
| Field | Required | Description |
|---|---|---|
cloudflare_api_token |
Yes | Cloudflare API token. |
zone |
Yes | Cloudflare zone name. |
dns_entries |
Yes | Hostnames to update (A and optional AAAA). |
record_ttl |
No | TTL in seconds (default 120). |
ipv6_enabled |
No | Set false to skip AAAA updates (default true). |
nest_router_url |
No | Nest / Google Wifi base URL. Omitted = http://<LAN>.1 from your default route. Set null to skip Nest. |
CLOUDFLARE_API_TOKEN in the environment overrides only the token field in the file.
IP discovery
IPv4
- Google Nest / Wifi —
GET {nest_router_url}/api/v1/status→wan.localIpAddress - Fallback —
https://checkip.amazonaws.com
IPv6
The Nest status API does not expose WAN IPv6. When ipv6_enabled is true:
https://api6.ipify.org(viacurl -6)https://ipv6.icanhazip.com
Usage
cloudflare-dns-updater # update when IPv4 or IPv6 changed
cloudflare-dns-updater -f # recheck Cloudflare even if local state is unchanged
cloudflare-dns-updater -d # dry-run (no Cloudflare calls, no state file writes)
cloudflare-dns-updater -v # verbose logging and discovery details
cloudflare-dns-updater -c /path/to/config.json
Run cloudflare-dns-updater -h for full option descriptions.
State is stored under ~/.local/state/cloudflare-dns-updater/ (override with XDG_STATE_HOME).
Run from a git checkout
./bin/cloudflare-dns-updater -v -d
The wrapper runs uv sync --group dev when .venv is missing or uv.lock has changed, then invokes the CLI. You can still use uv run cloudflare-dns-updater directly after a manual sync.
Development
uv sync --group dev
uv run ruff check .
uv run ruff format .
uv run mypy src/dns_updater
uv run pytest
uv run pytest -m integration # live network checks
Releases
Versioning and PyPI publish are documented in RELEASING.md. End users install with pipx install cloudflare-dns-updater.
Repository setup
This repo follows the-hcma conventions. Validate with:
scripts/check-repo-practices --repo the-hcma/cloudflare-dns-updater --suggest
See GRAPHITE.md for stacked PRs and the merge-it merge queue.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cloudflare_dns_updater-0.1.0.tar.gz.
File metadata
- Download URL: cloudflare_dns_updater-0.1.0.tar.gz
- Upload date:
- Size: 65.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b76a36457a327e01ac12f95d2e1d0b62e562fb5c420752ba9a83ede547d65cf0
|
|
| MD5 |
31b2e429a1824b727badd448d7a59e87
|
|
| BLAKE2b-256 |
2c99c75e35124bf59c291fe58161ee974ec3afd2019236b063faa1ff1b0b2fe0
|
Provenance
The following attestation bundles were made for cloudflare_dns_updater-0.1.0.tar.gz:
Publisher:
release-please.yml on the-hcma/cloudflare-dns-updater
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cloudflare_dns_updater-0.1.0.tar.gz -
Subject digest:
b76a36457a327e01ac12f95d2e1d0b62e562fb5c420752ba9a83ede547d65cf0 - Sigstore transparency entry: 1615000600
- Sigstore integration time:
-
Permalink:
the-hcma/cloudflare-dns-updater@d019da8eeeee917b2aab77a18e65d186dd3c1a53 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/the-hcma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@d019da8eeeee917b2aab77a18e65d186dd3c1a53 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file cloudflare_dns_updater-0.1.0-py3-none-any.whl.
File metadata
- Download URL: cloudflare_dns_updater-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51dfafb9f8e6c13ebf7334125383d00626792bfee34726c23920ed1a4861eb35
|
|
| MD5 |
688bf2e2d3fa8be2218dc70b90d85ae7
|
|
| BLAKE2b-256 |
3ba71a5b60599dd59a7645e6e5d14f48ebfc218b77a71162934ba3641bfe49d8
|
Provenance
The following attestation bundles were made for cloudflare_dns_updater-0.1.0-py3-none-any.whl:
Publisher:
release-please.yml on the-hcma/cloudflare-dns-updater
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cloudflare_dns_updater-0.1.0-py3-none-any.whl -
Subject digest:
51dfafb9f8e6c13ebf7334125383d00626792bfee34726c23920ed1a4861eb35 - Sigstore transparency entry: 1615000601
- Sigstore integration time:
-
Permalink:
the-hcma/cloudflare-dns-updater@d019da8eeeee917b2aab77a18e65d186dd3c1a53 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/the-hcma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@d019da8eeeee917b2aab77a18e65d186dd3c1a53 -
Trigger Event:
workflow_dispatch
-
Statement type: