Troubleshooting¶
Common issues and solutions when running Ferrous DNS.
Port 53 Already in Use¶
Symptom¶
Cause¶
On most Linux distributions, systemd-resolved occupies port 53.
Solution¶
Then update /etc/resolv.conf to point to Ferrous DNS or a public resolver:
Edit /etc/systemd/resolved.conf:
Then restart:
DNS Queries Not Being Resolved¶
Check 1: Is the server running?¶
Check 2: Can you reach the DNS port?¶
If this times out, check firewall rules:
# Check if port 53 is open
sudo ss -tulnp | grep :53
# Open port 53 (if using ufw)
sudo ufw allow 53/udp
sudo ufw allow 53/tcp
Check 3: Are upstream servers reachable?¶
Check the dashboard at Settings > System Status > Upstream Health. If all upstreams show "Unhealthy":
- Verify your upstream URLs are correct in
ferrous-dns.toml - Check network connectivity from the server:
dig @8.8.8.8 example.com - If using DoH/DoT/DoQ upstreams, ensure outbound ports 443/853 are open
Dashboard Not Loading¶
Check the web port¶
If no response:
- Verify
web_portinferrous-dns.toml(default:8080) - Check if the port is open:
sudo ss -tulnp | grep :8080 - Check Docker port mappings if running in a container
Blank page or JavaScript errors¶
- Clear browser cache and reload
- Check the browser console (F12) for errors
- Verify you are not using a very old browser — the dashboard requires ES2020 support
DoT / DoH Not Working¶
Check TLS certificates¶
# Verify cert file exists and is valid
openssl x509 -in /path/to/cert.pem -text -noout
# Check key matches cert
openssl x509 -in cert.pem -modulus -noout | md5sum
openssl rsa -in key.pem -modulus -noout | md5sum
# Both should output the same hash
Check the server logs¶
# Docker
docker logs ferrous-dns 2>&1 | grep -i tls
# Binary
RUST_LOG=debug ./ferrous-dns --config ferrous-dns.toml 2>&1 | grep -i tls
If you see "TLS certificate not found, skipping DoT/DoH listeners", verify the file paths in:
Self-signed certificate rejected¶
Browsers reject DoH to servers with self-signed certificates. Options:
- Use a Let's Encrypt certificate
- Import the self-signed CA into your OS trust store
- For DoT on Android/iOS, self-signed certificates are generally accepted
High Memory Usage¶
Check cache size¶
The DNS cache is the largest in-memory structure. Reduce it if memory is constrained:
Check SQLite memory-mapped I/O¶
[database]
sqlite_mmap_size_mb = 32 # reduce from 64 for low-memory systems
sqlite_cache_size_kb = 8192 # reduce from 16384
Raspberry Pi / low-memory devices¶
Use the RPi-optimized profile from the cache configuration:
[dns]
cache_max_entries = 50000
cache_compaction_interval = 300
[database]
sqlite_cache_size_kb = 8192
sqlite_mmap_size_mb = 32
Database Locked / SQLITE_BUSY¶
Symptom¶
Cause¶
SQLite WAL mode allows concurrent reads but serializes writes. Under very high query logging load, the write lock can be contended.
Solution¶
Increase the busy timeout:
Or reduce write pressure by sampling queries:
[database]
query_log_sample_rate = 10 # log 1 in 10 queries instead of all
query_log_max_batch_size = 5000 # larger batches = fewer transactions
PROXY Protocol Rejecting Connections¶
Symptom¶
All TCP DNS and DoT connections fail after enabling PROXY Protocol.
Cause¶
When proxy_protocol_enabled = true, the server expects every TCP connection to start with a PROXY Protocol v2 header. Direct client connections (without a load balancer) do not include this header.
Solution¶
Only enable PROXY Protocol when a compatible load balancer (HAProxy, AWS NLB, nginx stream module) is always in front:
UDP DNS is not affected — PROXY Protocol only applies to TCP and DoT listeners.
Docker Networking Issues¶
Host network mode (recommended)¶
Host mode gives Ferrous DNS direct access to the network, enabling accurate client IP detection.
Bridge mode¶
If you must use bridge mode, map the ports explicitly:
Client IP detection in bridge mode
In bridge mode, all queries appear to come from the Docker gateway IP (usually 172.17.0.1). Client-specific features (groups, per-client policies) will not work correctly. Use host network mode for accurate client detection.
Increasing Log Verbosity¶
For debugging, increase the log level:
Or via environment variable:
Warning
debug and trace levels produce significant log volume under load. Use only for troubleshooting, then revert to info.