A lightweight Python daemon that keeps your Cloudflare DNS records in sync with your network's public IP address — built for home labs, self-hosted infrastructure, and lightweight production environments.
- Features
- Requirements
- Installation
- Configuration
- Usage
- Logs & Monitoring
- Updating
- Uninstalling
- Contributing
- License
- Automatic public IP detection and DNS record syncing
- Optional
cloudflaredhealth check per record before updating - Dynamic config reload — changes to
config.yamltake effect on the next cycle without a restart - Structured logging with configurable log level
- Isolated Python environment (
venv) provisioned by the installer - Managed by
systemdwith automatic restart on failure
- Linux (Debian, Ubuntu, CentOS, or compatible)
- Python 3.6+
sudoaccess for installation and service management- Cloudflare API token with
Zone:ReadandDNS:Editpermissions
curl -sSL https://raw.githubusercontent.com/KAIKOAUGUSTIN/dnscript/main/install.sh -o install.sh
chmod +x install.sh
sudo ./install.shThe installer sets up the following layout and exits:
/opt/ddns-updater/
├── ddns_updater.py
├── config.yaml
└── venv/
/etc/systemd/system/
└── ddns-updater.service
/var/log/
└── ddns_updater.log
An uninstall.sh script is also saved to the directory from which you ran the installer.
Once installation is complete, edit the config before starting the service:
sudo nano /opt/ddns-updater/config.yaml
sudo systemctl start ddns-updater.serviceAll configuration lives in /opt/ddns-updater/config.yaml. The script reads this file on every update cycle, so most changes apply without a service restart.
settings:
update_interval: 300
log_level: INFO
log_file: "/var/log/ddns_updater.log"
cloudflare:
email: "[email protected]"
api_token: "YOUR_API_TOKEN"
zone_id: "YOUR_ZONE_ID"
dns_records:
- name: "home.example.com"
type: "A"
proxied: false
use_cloudflared: false
- name: "nas.example.com"
type: "A"
proxied: true
use_cloudflared: true| Key | Type | Description |
|---|---|---|
update_interval |
int | Seconds between update cycles. Default: 300 |
log_level |
string | Logging verbosity. One of DEBUG, INFO, WARNING, ERROR |
log_file |
string | Path to the log file |
| Key | Description |
|---|---|
email |
Email associated with your Cloudflare account |
api_token |
Cloudflare API token with Zone:Read and DNS:Edit permissions |
zone_id |
The zone ID for your domain |
| Key | Type | Description |
|---|---|---|
name |
string | Fully qualified domain name to update |
type |
string | DNS record type (e.g. A) |
proxied |
bool | Whether to proxy traffic through Cloudflare |
use_cloudflared |
bool | If true, checks that cloudflared is active via systemctl is-active before updating this record |
The service starts automatically on boot. To manage it manually:
# Start / stop / restart
sudo systemctl start ddns-updater.service
sudo systemctl stop ddns-updater.service
sudo systemctl restart ddns-updater.service
# Check current status
sudo systemctl status ddns-updater.service# Stream logs via journald
sudo journalctl -u ddns-updater.service -f
# Read the log file directly
sudo tail -n 200 /var/log/ddns_updater.logTo update the script without touching your configuration:
sudo systemctl stop ddns-updater.service
sudo curl -sSL https://raw.githubusercontent.com/KAIKOAUGUSTIN/dnscript/main/ddns_updater.py \
-o /opt/ddns-updater/ddns_updater.py
sudo chmod +x /opt/ddns-updater/ddns_updater.py
sudo systemctl start ddns-updater.serviceconfig.yaml is never overwritten by this process.
Run the uninstall.sh that was downloaded alongside the installer:
chmod +x ./uninstall.sh
sudo ./uninstall.shYou will be prompted to confirm before anything is removed. The script will:
- Stop and disable the
systemdservice - Remove
/etc/systemd/system/ddns-updater.service - Remove
/opt/ddns-updater/(including thevenv) - Remove
/var/log/ddns_updater.log - Attempt to uninstall
requestsandPyYAMLglobally viapip3 uninstall -y - Run
systemctl daemon-reload
- Fork the repository
- Create a branch for your change (
git checkout -b feat/your-feature) - Commit your changes
- Open a Pull Request describing the motivation and what changed
Please open an Issue first for significant changes so we can discuss the approach before you invest time in the implementation.
Distributed under the GPL-3.0 License. See LICENSE for details.