DNSCTL is a local infrastructure tool for managing Cloudflare DNS records safely. It brings a Git-backed state model, drift detection, and a plan/apply workflow to DNS — so you always know what changed, when, and why.
It ships as both a CLI for scripting and automation, and a GUI for interactive use — both powered by the same reconciliation engine.
1. sync Pull live DNS records from Cloudflare into local state
2. edit Add, edit, or delete records locally (no live changes yet)
3. plan Preview exactly what will be pushed to Cloudflare
4. apply Push the confirmed changes
5. history Every change auto-committed to a local Git repo
No change touches Cloudflare until you explicitly apply it.
- Drift Detection — Spot out-of-band dashboard changes before they cause issues
- Plan / Apply Workflow — Review a diff before any record is touched
- Git-Backed History — Every sync and edit auto-committed; full rollback support
- Secure Token Storage — AES-256-GCM encrypted, key derived via PBKDF2, stored in OS keyring
- Session Locking — Token cached in memory, auto-expires after inactivity
- Multi-Account — Manage multiple Cloudflare accounts; one master password unlocks all
- Protected Records — System-level (NS) and user-defined guards that require
--forceto override - CLI + GUI Parity — Every feature available in both interfaces
pip install dnsctl-appRequires Python 3.11+ and Git. On Linux, ensure a keyring backend is available (e.g.
gnome-keyringorkwallet).
Download the bundled installer from the Releases page.
Includes both CLI (dnsctl.exe) and GUI (dnsctl-g.exe) with all dependencies — no Python required.
git clone https://github.com/dhivijit/dnsctl.git
cd dnsctl
pip install -e .dnsctl loginYou'll be prompted for an account name, your Cloudflare API token, and a master password. The token is encrypted and stored in your OS keyring — never in plaintext.
dnsctl unlockDecrypts the token into a short-lived session. One password unlocks all your accounts at once.
dnsctl syncdnsctl add --type A --name staging.example.com --content 1.2.3.4Nothing is sent to Cloudflare yet.
dnsctl plandnsctl applyLaunch the graphical interface:
dnsctl-gFeatures:
- Zone selector with drift status indicator
- Record table with add / edit / delete dialogs
- Sync, Plan, and Apply controls
- History viewer and rollback
- Multi-account switcher
- Session unlock dialog
The GUI uses the same reconciliation engine as the CLI — no feature gap between them.
dnsctl login # Add a Cloudflare account (encrypted)
dnsctl unlock # Unlock session with master password
dnsctl lock # Lock session manually
dnsctl logout # Remove stored credentials for current accountdnsctl sync [-z ZONE] # Pull records from Cloudflare
dnsctl status # Show accounts, zones, and session state
dnsctl diff [-z ZONE] # Show drift between local state and Cloudflare
dnsctl plan [-z ZONE] # Preview what apply would push
dnsctl apply [-z ZONE] # Push planned changes to Cloudflarednsctl add --type A --name sub.example.com --content 1.2.3.4
dnsctl edit --type A --name sub.example.com --content 5.6.7.8
dnsctl rm --type A --name sub.example.comdnsctl protect --type A --name example.com --reason "Critical root record"
dnsctl unprotect --type A --name example.com
dnsctl protecteddnsctl log
dnsctl rollback <commit_sha>dnsctl export [-z ZONE] [-o output.json]
dnsctl import zone.jsondnsctl accounts list
dnsctl accounts switch <alias>
dnsctl accounts remove <alias>DNSCTL supports multiple Cloudflare accounts side by side, each with isolated zone state.
# Add accounts
dnsctl login # prompts for account name + token + password
dnsctl login --label "Work" # with explicit label
# Switch between accounts
dnsctl accounts list
dnsctl accounts switch work
# Remove an account
dnsctl accounts remove personalAll accounts share a single master password. Unlocking one automatically unlocks all others in the same session.
- API token encrypted with AES-256-GCM
- Encryption key derived via PBKDF2-HMAC-SHA256 (200,000 iterations)
- Encrypted blob stored in the OS keyring (Windows Credential Manager / macOS Keychain / Linux Secret Service)
- Plaintext token held in memory only for the duration of the session, then discarded
- Session expires automatically after inactivity (default: 15 minutes)
dnsctl lockexpires the session immediatelydnsctl logoutremoves all stored credentials for an account
Two layers:
- System-protected — NS records are always protected
- User-defined — mark any record with
dnsctl protect; requires--forceto override in apply
Pull requests are welcome. For larger changes, open an issue first to discuss the approach.
git clone https://github.com/dhivijit/dnsctl.git
cd dnsctl
pip install -e ".[dev]"
pytestMIT License — © Dhivijit

