DNS server with web management UI, DHCP integration, filtering, and NTP support
1.6K
A comprehensive DNS server solution with an intuitive web interface, designed for network administrators and self-hosters.
š Full documentation: https://docs.codexs.com.br/codexdns/ā
docker run -d \
--name codexdns \
--restart unless-stopped \
-p 8080:8080 \
-p 53:53/udp \
-p 53:53/tcp \
-v codexdns-data:/app/data \
-v codexdns-config:/app/config \
-v codexdns-logs:/app/logs \
-v codexdns-certs:/app/certs \
marcuoli/codexdns:latest
Access the web UI at: http://localhost:8080ā
docker run -d \
--name codexdns \
--restart unless-stopped \
-p 8080:8080 \
-p 8443:8443 \
-p 53:53/udp \
-p 53:53/tcp \
-p 853:853/tcp \
-p 123:123/udp \
-v codexdns-data:/app/data \
-v codexdns-config:/app/config \
-v codexdns-logs:/app/logs \
-v codexdns-certs:/app/certs \
-e TZ=America/New_York \
-e CODEXDNS_ADMIN_PASSWORD=your-strong-admin-password \
-e CODEXDNS_SESSION_SECRET=$(openssl rand -hex 32) \
marcuoli/codexdns:latest
services:
codexdns:
image: marcuoli/codexdns:latest
container_name: codexdns
restart: unless-stopped
ports:
- "8080:8080" # HTTP Web UI
- "8443:8443" # HTTPS Web UI
- "53:53/udp" # DNS
- "53:53/tcp" # DNS
- "853:853/tcp" # DNS-over-TLS
- "123:123/udp" # NTP
volumes:
- codexdns-data:/app/data
- codexdns-config:/app/config
- codexdns-logs:/app/logs
- codexdns-certs:/app/certs
environment:
- TZ=America/New_York
- CODEXDNS_ADMIN_PASSWORD=your-strong-admin-password
- CODEXDNS_SESSION_SECRET=replace-with-output-of-openssl-rand-hex-32
volumes:
codexdns-data:
codexdns-config:
codexdns-logs:
codexdns-certs:
adminCODEXDNS_ADMIN_PASSWORD environment variableOption A ā provide a password at startup (recommended):
docker run -d \
--name codexdns \
-e CODEXDNS_ADMIN_PASSWORD=your-strong-password \
...
The password must be at least 12 characters. The admin account is created with this password on first boot; if the account already exists the seed step is skipped.
Option B ā auto-generated password (if CODEXDNS_ADMIN_PASSWORD is not set):
CodexDNS generates a strong random 24-character password and prints it once to the startup logs. Retrieve it before the first login:
docker logs codexdns | grep -A1 'CODEXDNS ADMIN PASSWORD'
You will also be prompted to change this password on your first login.
| Port | Protocol | Service | Required |
|---|---|---|---|
| 8080 | TCP | HTTP Web UI | ā Yes |
| 8443 | TCP | HTTPS Web UI | Optional |
| 53 | UDP/TCP | DNS Server | ā Yes (if using DNS) |
| 853 | TCP | DNS-over-TLS | Optional |
| 443 | TCP | DNS-over-HTTPS | Optional |
| 123 | UDP | NTP Server | Optional |
| Container Path | Purpose | Required |
|---|---|---|
/app/data | SQLite database, blocklists | ā Required |
/app/config | Configuration files | ā Required |
/app/logs | Application logs | Recommended |
/app/certs | TLS/SSL certificates | Required for HTTPS/DoT |
All CODEXDNS_* variables map directly to config file fields via the CODEXDNS_ prefix
(e.g. CODEXDNS_HTTP_PORT overrides http_port). Environment variables always take
precedence over values in config.json.
| Variable | Default | Description |
|---|---|---|
TZ | UTC | Timezone (e.g., America/New_York) |
CODEXDNS_CONFIG_FILE | /app/config/config.json | Custom config file path |
| Web UI | ||
CODEXDNS_HTTP_PORT | 8080 | HTTP web UI port |
CODEXDNS_HTTPS_ENABLED | false | Enable HTTPS web UI |
CODEXDNS_HTTPS_PORT | 8443 | HTTPS web UI port |
CODEXDNS_GIN_MODE | release | Gin framework mode (debug/release) |
| DNS Server | ||
CODEXDNS_DNS_HOST | 0.0.0.0 | DNS bind address |
CODEXDNS_DNS_PORT | 53 | DNS port (UDP + TCP) |
CODEXDNS_UPSTREAM_SERVERS | 8.8.8.8:53;1.1.1.1:53 | Semicolon-separated upstream DNS forwarders |
CODEXDNS_UPSTREAM_STRATEGY | ordered | Upstream selection (ordered/round-robin/fastest-response/lowest-latency) |
| Services | ||
CODEXDNS_NTP_ENABLED | false | Enable built-in NTP server |
CODEXDNS_DHCP_ENABLED | false | Enable built-in DHCP server |
| Database | ||
CODEXDNS_DB_DRIVER | sqlite | Database driver (sqlite/postgres/mysql) |
CODEXDNS_DB_DSN | /app/data/codexdns.db | Database path or DSN |
| Cache | ||
CODEXDNS_CACHE_BACKEND | redis | Cache backend (redis/memory/none) |
CODEXDNS_CACHE_ENABLED | true | Enable DNS query caching |
CODEXDNS_REDIS_ADDR | localhost:6379 | Redis server address (when cache_backend=redis) |
| Logging | ||
CODEXDNS_LOG_LEVEL | info | Log level (debug/info/warn/error) |
| Security | ||
CODEXDNS_ADMIN_PASSWORD | (auto-generated) | Password for the built-in admin account. Printed once to the startup log if not set. |
CODEXDNS_SESSION_SECRET | (required in production) | Secret used to sign session cookies. Must be at least 32 characters. Generate with openssl rand -hex 32. Startup aborts in release mode if missing or too short. |
singleflight deduplicationCodexDNS is built on Go's native concurrency model ā lightweight goroutines scheduled by the Go runtime across all available CPU cores. There is no thread pool to size; the runtime automatically parallelises work across every core the container is given.
Each protocol server and background service runs in its own independent goroutine, so a restart of the DNS server (via the web UI or API) never pauses the HTTP/HTTPS interface, and vice versa.
| Goroutine / Worker | Role |
|---|---|
| HTTP server | Web UI and REST API |
| HTTPS server | TLS-terminated Web UI and REST API |
| DNS UDP + TCP | Standard DNS on port 53 |
| DNS-over-TLS (DoT) | Encrypted DNS on port 853 |
| DNS-over-HTTPS (DoH) | DNS via HTTPS on port 443 |
| DNS-over-QUIC (DoQ) | DNS over HTTP/3 |
| NTP server | Time synchronisation on port 123 |
| Stats service | Periodic query-rate aggregation |
| Async log writer | Buffered write queue (up to 10,000 in-flight entries) |
| DNS query DB logger | Async persistence queue (up to 20,000 in-flight entries) |
| Client tracking workers | Configurable pool ā reverse DNS / mDNS / NetBIOS discovery |
| Filter list updater | Background blocklist refresh |
| TLS cert renewal monitor | Automatic certificate re-issue |
| Prometheus exporter | Metrics collection and exposure |
| Signal handler | Clean shutdown on SIGINT / SIGTERM |
Each incoming DNS query is dispatched to its own goroutine. Two mechanisms prevent overload:
dns_max_concurrent_queries ā configurable hard cap; queries that exceed the limit are dropped gracefully with a counter exposed in the dashboard and Prometheus metrics.singleflight deduplication ā identical upstream forwarding requests that arrive simultaneously are collapsed into a single round-trip, reducing upstream load and latency spikes under burst traffic.GOMAXPROCSGo 1.25 is fully cgroup-aware: when you set --cpus (or a cgroup CPU quota) on a container, the runtime reads the quota and automatically caps GOMAXPROCS to match ā no extra configuration needed.
# Give CodexDNS 2 vCPUs; GOMAXPROCS will be set to 2 automatically
docker run -d --cpus="2" --name codexdns ...
For single-core environments (e.g. a small home Raspberry Pi) CodexDNS works fine ā goroutines that are waiting on I/O (network, disk) yield the CPU automatically, so even one vCPU handles typical home DNS load with headroom to spare.
| Deployment scenario | Recommended vCPUs | Notes |
|---|---|---|
| Home / lab (< 50 clients) | 1 | Default settings work fine |
| Small office (50ā200 clients) | 2 | Consider increasing dns_client_tracking_workers |
| Medium network (200ā1 000 clients) | 2ā4 | Enable Redis caching; tune dns_max_concurrent_queries |
| Large network (1 000+ clients) | 4+ | Use PostgreSQL or MySQL; Redis strongly recommended |
On first start, CodexDNS copies its built-in default configuration to /app/config/config.json if no config file exists. You can then edit it via the web UI or by mounting your own file. For a full list of configuration parameters see the Configuration Referenceā .
docker run -d \
--name codexdns \
-v /path/to/config.json:/app/config/config.json \
-v codexdns-data:/app/data \
-v codexdns-logs:/app/logs \
-v codexdns-certs:/app/certs \
-p 8080:8080 -p 53:53/udp -p 53:53/tcp \
marcuoli/codexdns:latest
A minimal config.json to get started:
{
"http_port": "8080",
"dns_host": "0.0.0.0",
"dns_port": "53",
"db_driver": "sqlite",
"db_dsn": "/app/data/codexdns.db",
"cache_backend": "memory",
"log_level": "info",
"upstream_servers": ["8.8.8.8:53", "1.1.1.1:53"],
"upstream_strategy": "round-robin"
}
# View logs
docker logs codexdns
# Follow logs in real-time
docker logs -f codexdns
# View container status
docker ps -a | grep codexdns
# Check health endpoint
docker exec codexdns wget -qO- http://localhost:8080/health
# Access logs directory (if mounted)
docker exec codexdns ls -la /app/logs
Full documentation is available at https://docs.codexs.com.br/codexdns/ā
| Topic | URL |
|---|---|
| š Overview & Architecture | https://docs.codexs.com.br/codexdns/overview/ā |
| š Installation | https://docs.codexs.com.br/codexdns/installation/ā |
| āļø Configuration Reference | https://docs.codexs.com.br/codexdns/configuration/ā |
| š DNS Setup | https://docs.codexs.com.br/codexdns/dns/ā |
| š”ļø Filtering & Policies | https://docs.codexs.com.br/codexdns/filtering/ā |
| š NTP Server | https://docs.codexs.com.br/codexdns/ntp/ā |
| š§ Administration | https://docs.codexs.com.br/codexdns/administration/ā |
| š Deployment (HTTPS, production) | https://docs.codexs.com.br/codexdns/deployment/ā |
| š Report Issues | https://github.com/marcuoli/codexdns/issuesā |
| š¬ Discussions | https://github.com/marcuoli/codexdns/discussionsā |
| š¦ Source Code | https://github.com/marcuoli/codexdnsā |
CODEXDNS_ADMIN_PASSWORD to a strong password before first boot; if omitted, a random 24-character password is auto-generated and printed once to the startup logCODEXDNS_SESSION_SECRET to a unique random string of at least 32 characters; startup will abort in release (production) mode if this is missing, too short, or left as a placeholder ā generate one with openssl rand -hex 32/app/certs)MIT License ā see https://github.com/marcuoli/codexdns/blob/main/LICENSEā
Built with: Go, Gin, GORM, Templ, TailwindCSS, Alpine.js, HTMX
Base image: Alpine Linux 3.19
Architecture: Multi-stage optimized build (~50 MB)
Content type
Image
Digest
sha256:a2313d5d1ā¦
Size
50.7 MB
Last updated
16 days ago
docker pull marcuoli/codexdns