Curt's Dynamic DNS Updater is a Python script designed to update DNS records automatically for dynamic IP addresses. This solution supports multiple DNS providers including Cloudflare.
- Automatic IP detection and DNS record update
- Support for multiple DNS providers
- Configurable via an INI file
- Runs continuously with a configurable check interval
- Optional self‑updater that pulls new versions from Git
- Rotating log file with configurable path, level, and size
- Python 3.12
requestslibrary
-
Update your package list:
sudo apt update
-
Install dependencies:
sudo apt install -y software-properties-common
-
Add the deadsnakes PPA:
sudo add-apt-repository ppa:deadsnakes/ppa sudo apt update
-
Install Python 3.12:
sudo apt install -y python3.12 python3.12-venv python3.12-dev
-
Clone the repository:
git clone https://github.com/cpjet64/curtsddns.git cd curtsddns -
Create a virtual environment:
python3.12 -m venv venv
-
Activate the virtual environment:
source venv/bin/activate -
Install the required dependencies:
pip install requests
-
Configure your DNS settings in the
config.inifile usingconfig.ini.exampleas a template:cp config.ini.example config.ini
The config.ini file should be structured as follows:
[settings]
DNS_PROVIDER = cloudflare
CHECK_INTERVAL = 60 ; seconds between DNS checks
AUTO_UPDATE = false ; enable/disable Git-based self-update
AUTO_UPDATE_INTERVAL = 3600 ; seconds between update checks
[logging]
LOG_FILE = curtsddns.log ; path to log file (absolute or relative)
LOG_LEVEL = INFO ; DEBUG, INFO, WARNING, ERROR, CRITICAL
LOG_MAX_BYTES = 1048576 ; max size in bytes before rotation
LOG_BACKUP_COUNT = 5 ; how many rotated files to keep
[cloudflare]
CLOUDFLARE_API_TOKEN = your_cloudflare_api_token
CLOUDFLARE_ZONE_ID = your_cloudflare_zone_id
CLOUDFLARE_RECORD_NAME = your_dns_record_nameTo start the script, simply run:
python curtsddns.pyFor continuous operation, you can set up a systemd service:
Copy the curtsddns.service file to /etc/systemd/system/ and then modify as needed:
sudo cp curtsddns.service /etc/systemd/system/
sudo nano /etc/systemd/system/curtsddns.serviceHave the file created for you using the current user and file location:
echo "[Unit]
Description=Curt's Dynamic DNS Updater Service
After=network.target
[Service]
Type=simple
User=$(whoami)
WorkingDirectory=$(pwd)
ExecStart=$(pwd)/venv/bin/python $(pwd)/curtsddns.py
Restart=on-failure
[Install]
WantedBy=multi-user.target" | sudo tee /etc/systemd/system/curtsddns.serviceReload the systemd daemon:
sudo systemctl daemon-reloadEnable and start the service:
sudo systemctl enable curtsddns
sudo systemctl start curtsddns- curtsddns.py: Main script for updating DNS records.
- cloudflare_module.py: Module for handling Cloudflare DNS updates.
- config.ini: Configuration file (create from config.ini.example).
- config.ini.example: Example configuration file.
- curtsddns.service: Systemd service file for running the script as a service.
- Dockerfile:Docker configuration file.
To run Curt's Dynamic DNS Updater in a Docker container, follow these steps:
- Docker installed on your system
-
Clone the repository:
git clone https://github.com/cpjet64/curtsddns.git cd curtsddns -
Configure your DNS settings in the
config.inifile usingconfig.ini.exampleas a template:cp config.ini.example config.ini
Modify your
config.iniaccording to your environment:nano config.ini
The
config.inifile should be structured as follows:[settings] DNS_PROVIDER = cloudflare CHECK_INTERVAL = 60 AUTO_UPDATE = false AUTO_UPDATE_INTERVAL = 3600 [logging] LOG_FILE = curtsddns.log LOG_LEVEL = INFO LOG_MAX_BYTES = 1048576 LOG_BACKUP_COUNT = 5 [cloudflare] CLOUDFLARE_API_TOKEN = your_cloudflare_api_token CLOUDFLARE_ZONE_ID = your_cloudflare_zone_id CLOUDFLARE_RECORD_NAME = your_dns_record_name
-
Build the Docker image:
docker build -t curtsddns . -
Run the Docker container:
docker run -d --restart unless-stopped --name curtsddns -v $(pwd)/config.ini:/app/config.ini curtsddns-druns the container in detached mode.--name curtsddnsgives the container a name.-v $(pwd)/config.ini:/app/config.inimounts theconfig.inifile from the host to the container.
-
To stop the container:
docker stop curtsddns
-
To start the container:
docker start curtsddns
-
To view the container logs:
docker logs curtsddns
-
To remove the container:
docker rm curtsddns
- Ensure that the
config.inifile is properly configured before running the container. - You can customize the
Dockerfileand Docker run command to suit your specific needs.
By following these steps, you can easily run Curt's Dynamic DNS Updater in a Docker container, simplifying deployment and management.
Curt's DDNS can optionally keep itself up to date by pulling the latest changes from the Git remote and restarting the process.
- The auto‑updater is disabled by default. Enable it via
config.ini:[settings] AUTO_UPDATE = true AUTO_UPDATE_INTERVAL = 3600
- Requirements:
- The app must be running from a git clone of this repository.
- A remote named
originmust point to your GitHub repo. gitmust be installed and available inPATHfor the service user.
- Behavior:
- Every
AUTO_UPDATE_INTERVALseconds, the app compares the localHEADtoorigin/HEAD. - If different, it runs
git pull --ff-onlyand then re‑execs the Python process (os.execv) so the new code is loaded. - All actions and failures are logged via the configured logger.
- Every
- Recommendation:
- Use an interval of at least 1 hour (
3600) to avoid unnecessary traffic.
- Use an interval of at least 1 hour (
If auto‑update fails (no network, git error, etc.), the app logs a warning/error and continues running with the existing code.
The service uses Python's logging with a RotatingFileHandler:
- Configuration (in
config.ini):[logging] LOG_FILE = /var/log/curtsddns.log LOG_LEVEL = INFO LOG_MAX_BYTES = 1048576 LOG_BACKUP_COUNT = 5
LOG_FILEcan be absolute (e.g./var/log/curtsddns.log) or relative to the app directory.- When the log file reaches
LOG_MAX_BYTES, it rotates and keeps up toLOG_BACKUP_COUNTold files. - Logs are written both to the file and to stdout/stderr, so they also appear in
journalctlwhen run under systemd.
Make sure the service user has write permissions to the directory containing LOG_FILE (e.g. chown or adjust the path).
This project is licensed under the MIT License.
Contributions are welcome! Please fork the repository and submit a pull request.
For support or inquiries, please contact Curt at curt@curtpme.com.