mirror of
https://git.private.coffee/PrivateCoffee/mallarddns.git
synced 2026-10-23 16:04:49 +05:30
Dynamic DNS for Your Hosts
Request a hostname under our DynDNS zones and keep it automatically updated with your current IP.
- Python 70.7%
- HTML 24.9%
- CSS 4%
- Shell 0.3%
- Dockerfile 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| .vscode | ||
| contrib/podman | ||
| mallarddns | ||
| scripts | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| .snapshotignore | ||
| config.dist.yaml | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
MallardDNS
A Django-based DNS server for small networks. Serves authoritative zones, resolves recursively or via upstream forwarders, supports DNSSEC validation, hosts-file and RPZ block lists, and provides a DynDNS service with email verification.
Features
- Authoritative DNS — manage zones and records through a web UI or REST API
- Recursive resolution — full iterative resolver with optional DNSSEC validation
- Forwarding — per-domain forwarding rules with fallback to iterative resolution
- Block lists — hosts-file and RPZ format imports, with wildcard support
- DynDNS — token-based dynamic DNS updates with email verification and IP blocking
- Organizations — multi-tenant with owner/admin/member roles
- REST API — zone and record management via DRF
- Response cache — TTL-aware LRU cache for upstream query results
- Asyncio server — UDP and TCP listeners built on
asyncioprotocols
Requirements
- Python 3.10+
- A supported Django database (SQLite for development, PostgreSQL recommended for production)
- An SMTP server for DynDNS verification emails
Installation
git clone https://git.private.coffee/privatecoffee/mallarddns
cd mallarddns
python -m venv venv
venv/bin/pip install -e ".[production]"
Copy and edit the config:
cp config.dist.yaml config.yaml
$EDITOR config.yaml
Apply migrations and create a superuser:
venv/bin/python mallarddns/manage.py migrate
venv/bin/python mallarddns/manage.py createsuperuser
Collect static files:
venv/bin/python mallarddns/manage.py collectstatic
Configuration
MallardDNS reads config.yaml by default. Override the path with the MALLARDDNS_CONFIG environment variable.
| Key | Default | Description |
|---|---|---|
SECRET_KEY |
(required) | Django secret key |
DEBUG |
false |
Enable Django debug mode |
ALLOWED_HOSTS |
[] |
Hostnames the web server responds to |
SITE_URL |
Public base URL, used in DynDNS emails | |
TRUST_PROXY |
false |
Trust X-Forwarded-For from a reverse proxy |
DATABASE |
SQLite db.sqlite3 |
Django database config |
DNS_HOST |
0.0.0.0 |
IPv4 bind address for the DNS server |
DNS_HOST_V6 |
(disabled) | IPv6 bind address (e.g. ::) |
DNS_PORT |
5353 |
DNS listen port |
RECURSION_UPSTREAMS |
[] |
Upstream resolvers for forwarding mode |
RECURSION_UPSTREAM_PORT |
53 |
Port used when querying upstreams |
RECURSION_UPSTREAM_TIMEOUT |
3 |
Seconds before upstream query times out |
RECURSION_FALLBACK_TO_ITERATIVE |
true |
Fall back to iterative resolution if upstreams fail |
DYNDNS_TOKEN_EXPIRY |
24 |
Hours before DynDNS verification tokens expire (null = never) |
CACHE.remote_max_entries |
10000 |
Maximum entries in the upstream response cache |
CACHE.remote_min_ttl |
5 |
Minimum TTL (seconds) for cached upstream responses |
CACHE.remote_max_ttl |
86400 |
Maximum TTL (seconds) for cached upstream responses |
CACHE.negative_ttl_default |
30 |
TTL for negative (NXDOMAIN/empty) cache entries |
EMAIL |
SMTP config for DynDNS emails |
Running
Web server
venv/bin/gunicorn mallarddns.wsgi
Or behind a reverse proxy:
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Forwarded-For $remote_addr;
}
DNS server
venv/bin/python mallarddns/manage.py rundns
Options:
| Flag | Default | Description |
|---|---|---|
--host HOST |
DNS_HOST / DNS_HOST_V6 from config |
Address to listen on; may be repeated |
--port PORT |
DNS_PORT from config |
Port to listen on |
--recursive yes|no |
yes |
Enable iterative recursive resolution |
--forwarding yes|no |
no |
Enable forwarding to upstream resolvers |
--dnssec yes|no |
no |
Enable DNSSEC validation |
Example — listen on a non-standard port with forwarding:
venv/bin/python mallarddns/manage.py rundns --port 53 --forwarding yes
Example — dual-stack on port 53:
venv/bin/python mallarddns/manage.py rundns --host 0.0.0.0 --host :: --port 53
Maintenance commands
# Refresh IANA root server list
venv/bin/python mallarddns/manage.py update_root_servers
# Refresh IANA DNSSEC trust anchors
venv/bin/python mallarddns/manage.py update_trust_anchors
Development
venv/bin/pip install -e ".[dev]"
venv/bin/pre-commit install
Run tests:
venv/bin/python mallarddns/manage.py test mallarddns.records
Lint and format:
venv/bin/ruff check . --fix && venv/bin/ruff format .
venv/bin/djlint mallarddns --reformat
License
MIT — see LICENSE.