| nix | ||
| src/cloudns | ||
| .envrc | ||
| .gitignore | ||
| .python-version | ||
| flake.lock | ||
| flake.nix | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
Cloudns - A Cloudflare Dynamic DNS Solution
A DNS record updater for Cloudflare's DNS API.
Features
- Support for arbitrarily many domains and subdomains through a nested data structure
- Small codebase
- Logging
- NixOS module
How it works
This script determines the the current IP address by querying the resolvers defined in the config file. It then queries the subdomains' A records off of Cloudflare and compares their IP addresses to the current IP address. Should the IP address of a subdomain's A record not match your current IP address it will be updated. The subdomain's A record will be created should it not already exist.
Usage
First, get your User API Token from https://dash.cloudflare.com/profile/api-tokens. The token needs the Edit DNS permission set:
{
"api": {
"API Key": {
"example.com": [ "@", "www", "sub1" ],
"example.org": [ "@", "www", "sub1", "sub2" ]
},
"/path/to/a/file/containing/api_key": {
"example.at": [ "sub1" ],
"example.au": [ "sub1", "sub2" ]
}
},
"resolvers": [
"https://ifconfig.me/ip",
"https://me.gandi.net"
],
"log-path": "./log.jsonl"
}
Development
Build
nix build
# or
uv build
Development Environment
nix develop .#venv
# or
uv sync
Type Checking
nix develop .#venv -c ty check
# or
uv run ty check
Format
nix fmt
Lint
nix flake check
Nix
Add this to the modules.
inputs = {
cloudns.url = "git+https://git.krsnik.at/kristian/cloudns";
};
outputs = inputs: {
...
modules = [
inputs.cloudns.nixosModules.default
{
cloudns.enable = true;
cloudns.timer = 300;
cloudns.settings = {
api = {
"/path/to/a/file/containing/api_key" = {
"example.com" = ["@" "www"];
};
};
resolvers = [
"https://ifconfig.me/ip"
"https://me.gandi.net"
];
log_path = "/path/to/log/file.jsonl";
};
}
...
];
...
}
cloudns.timer specifies a timer in seconds when the script should be repeated.
Notes
Every invocation of the script causes at least 1 request to a resolver specified and 1 API call to Cloudflare per domain. Updating a subdomain's A record is 1 API request per subdomain, even if they share the same domain. Resolvers are queried in the order specified until one returns a valid IP address. It is also possible to define a path to a file with the API key written in it. This is good for environments where the config file has to be shared like in a nix project.
Limitations
- Only IPv4 addresses are supported