- Python 99.7%
- Shell 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The heading carried a robot emoji. In context it meant automation, the file being full of emoji headings, but the repository's rule against assistant markers is literal and a reader has no way to tell which sense was intended. A gear says automated without the ambiguity. |
||
| .forgejo/workflows | ||
| doc | ||
| img | ||
| packaging | ||
| scripts | ||
| src | ||
| .gitignore | ||
| CHANGELOG.md | ||
| LICENSE.txt | ||
| README.md | ||
| requirements-build.in | ||
| requirements-build.lock | ||
| requirements-dev.in | ||
| requirements-dev.lock | ||
| requirements.lock | ||
| requirements.txt | ||
| ROADMAP.md | ||
| ruff.toml | ||
| SECURITY.md | ||

desec-qt-dns
Manage your deSEC DNS zones, records, DNSSEC and API tokens from the desktop
For deSEC accounts.
An independent client for the deSEC API - not made by or affiliated with deSEC e.V.
Support: support@jdneer.com
deSEC hosts DNS zones for free, signs every one of them with DNSSEC, and is managed through a REST API. This is a desktop client for that API: zones and records, DNSSEC, bulk changes across many zones, API tokens, and a history you can roll back. It talks to the deSEC API and to nothing else.
What you get
- 🌐 Zones and records. Create and delete zones, with your account's zone quota in the header. 37 record types, each with a format hint, an example and validation as you type. Filter by name, type, content or TTL, and delete many records at once.
- 🔒 DNSSEC. DS and DNSKEY values ready to copy, a Chain of Trust card for subdomain zones, and an optional per-zone check, off by default, that says whether the parent really publishes a DS matching a key the zone serves.
- 🪄 DNS Record Wizard. 61 presets in 16 categories, from Google Workspace and Microsoft 365 to Mailgun, GitHub Pages and Matrix, applied to many zones in one run with a preview that flags conflicts. Separate modes take your own records, set up delegated subdomains, and build reverse DNS zones.
- 🔎 Search and Replace. Search every zone at once by name, type, content, TTL or zone, as plain text or a regex, then replace, rename, retime, delete or export what matched.
- 📦 Import and export. JSON, YAML, BIND zone files and djbdns/tinydns. Import appends, merges or replaces after a preview; export several zones to one ZIP.
- 🔑 Tokens. Create, edit and delete API tokens, with permissions, write policies per domain, expiry and subnet limits.
- ↩️ Queue and history. Every API call, pending and done, with its request and response; and a snapshot of the zone after every change that you can restore.
- 👥 Profiles. Several deSEC accounts side by side, each with its own token, cache, history and settings, and a passphrase of your own on any of them.
- 🧪 A demo account, so you can try this without a deSEC account. Create Demo Account, in the profile window, builds a profile of 140 generated zones with their records and tokens, from a fixed seed. It is sealed rather than merely pointed elsewhere: the API client is replaced by one that serves a local store and imports no HTTP library, and the DNSSEC worker never starts. Every name is reserved by RFC 2606 and every address by RFC 1918 or RFC 3849. It is fully editable, your changes are kept, and it says what it is in three places at once, so a screenshot of it cannot be mistaken for a real account.
Fluent Design, in light, dark, or following the system. Every page, panel and drawer is in doc/UI-FEATURES.md.
Install
AppImage (recommended)
Download deSEC-Qt-DNS-Manager-<version>-x86_64.AppImage from the
releases page, then:
chmod +x deSEC-Qt-DNS-Manager-*-x86_64.AppImage
./deSEC-Qt-DNS-Manager-*-x86_64.AppImage
One file with everything inside it, Python included. Nothing is installed:
deleting the file removes the app, and your settings stay in ~/.config/desecqt/.
RPM, for Fedora
sudo dnf config-manager addrepo --from-repofile=https://git.jdneer.com/api/packages/jd/rpm.repo
sudo rpm --import https://git.jdneer.com/jd.gpg
sudo dnf install desec-qt-dns
New releases then arrive with a normal sudo dnf upgrade. Start it from the
application menu or with desec-qt-dns.
From source
git clone https://git.jdneer.com/jd/desec-qt-dns.git
cd desec-qt-dns
python3 -m venv .venv
source .venv/bin/activate
pip install --require-hashes -r requirements.lock
python src/main.py
Older Fedora releases, a downloaded .rpm on its own, and what each package
targets and contains are in doc/INSTALL.md. The signing
key's fingerprint and what --require-hashes buys you are in
SECURITY.md.
Getting started
- Create an API token in your deSEC account at https://desec.io.
- Start the app and paste the token when it asks. It is kept encrypted in your profile; see Privacy for what that does and does not protect.
- Pick a zone on the DNS page. Its records load on the right, and Add Record slides in an editor with a hint and an example for each record type.
- Every change goes to deSEC through the API queue, one request at a time, at 0.5 requests per second by default. Bulk work is slow on purpose: doc/RATE-LIMIT.md explains why. Anything that deletes asks twice.
Zones and records show from the local cache first and refresh in the background, so the app opens with your zones straight away. F5 syncs now; the other shortcuts are in doc/UI-FEATURES.md.
deSEC signs every zone it hosts, but the DS record in the parent zone is yours to place: doc/DNSSEC-CHECKS.md covers where it goes and how to tell whether it worked.
Requirements
- A deSEC account and an API token
- x86_64 Linux: Debian 12 or newer (or equivalent) for the AppImage, a current Fedora for the RPM
git, for the zone history; without it everything else still works- From source: Python 3.13 or newer
Privacy
The app holds your DNS: every zone and record in the account, your token list, and the history of what you changed. None of it reaches the developer.
- It talks to the deSEC API and to nothing else. No telemetry, no analytics, no update checks, no server in between. Turning on Delegation and DNSSEC Checks (Settings → Advanced) is the one exception: it then queries the DNS root, your own resolver, or a DNS-over-HTTPS provider, whichever you pick there.
- The token is always encrypted, but by default that only obfuscates it.
Both halves of the key are readable by anyone who can read
~/.config/desecqt. A passphrase of your own, set per profile, is what makes it real: there is no recovery from forgetting one. - A passphrase covers the token and nothing else. Cached zone and record names, the queue history, the version history and the log are plain files on disk either way.
- Changes only when you ask. Syncing only reads, and deletes ask twice.
- No affiliation. This is an independent tool, not made by, endorsed by, or connected to deSEC e.V.
doc/PRIVACY.md has the full account: every host the app can reach, every file it writes, and what is in each one.
Documentation
| Document | What |
|---|---|
| doc/INSTALL.md | What each package targets, older Fedora, building from source |
| doc/UI-FEATURES.md | Every page, panel and drawer, and the keyboard shortcuts |
| doc/RECORD-MANAGEMENT.md | Record types, TTLs, batch actions, troubleshooting |
| doc/DNSSEC-CHECKS.md | Where the DS goes, the two per-zone icons, when checks run, how long answers are kept |
| doc/IMPORT_EXPORT.md | Import and export formats, modes and workflows |
| doc/RATE-LIMIT.md | Why requests are paced, and how to tune it |
| doc/API-NOTES.md | The API queue, retries and 429 handling |
| doc/CONFIG.md | Every setting with its default, and where files live |
| doc/PROFILES.md | Several accounts side by side, passphrases, the demo account |
| doc/PRIVACY.md | What it talks to, what it stores, what the passphrase protects |
| doc/CACHING.md | How the cache works |
| doc/LOGS-AND-NOTIFICATIONS.md | The log console, severity levels, the log file |
| doc/ARCHITECTURE.md | Modules, data flow and design |
| doc/RELEASE-PROCESS.md | Versioning, tagging and building releases |
| SECURITY.md | Reporting security issues, supply-chain hardening, package signing, token storage |
| CHANGELOG.md | What changed per release |
| ROADMAP.md | Planned work |
Support
support@jdneer.com for questions, bug reports and feature requests.
What helps in a report:
- The version, shown on the About page at the bottom of the sidebar.
- The Log Console, the lines around the problem. They name your zones and records, so cut anything you would rather not share. Turning on Debug mode in Settings first makes them more useful.
- The error text from the failed request's entry on the Queue page.
- What you did, step by step, and whether it happens again.
What not to send: your API token, or anything from ~/.config/desecqt. Between
them those files hold your token and every record in your account. Nothing in a
bug report needs them, and no reply will ever ask for them.
Security problems go to the same address, privately: see SECURITY.md.