# fancy-dns — example configuration. # # Every value below is a default; delete what you do not need. The admin API # rewrites this file when you save from the console, so keep it in git and # review the diff. version: 0 server: # In-flight upstream resolutions. Excess queries get SERVFAIL rather than # queueing without bound. max_concurrent: 1024 timeouts: udp: 2s tcp: 4s tls: 4s query: 5s upstream: 2s list_fetch: 60s dns: udp: ["0.0.0.0:53", "[::]:53"] tcp: ["0.0.0.0:53", "[::]:53"] # Advertised EDNS0 buffer size for our own answers. max_udp_size: 1232 serve_stale: 0s edns0: # Forward the client's EDNS-Client-Subnet so upstream picks a nearby # anycast location. client_subnet: true ipv4_bits: 24 ipv6_bits: 56 preserve: true dot: enabled: false listen: ["0.0.0.0:853"] cert_file: /etc/fancy-dns/tls/fullchain.pem key_file: /etc/fancy-dns/tls/privkey.pem min_version: "1.2" doh: enabled: false listen: ["0.0.0.0:443"] base_path: /dns-query cert_file: /etc/fancy-dns/tls/fullchain.pem key_file: /etc/fancy-dns/tls/privkey.pem min_version: "1.2" allow_post: true transport: mode: auto upstream: # parallel: race them, take the first good answer. random: try N at random. # failover: walk the list in order. policy: parallel max_attempts: 3 healthcheck_interval: 30s breaker_threshold: 5 breaker_cooldown: 30s servers: - addr: 9.9.9.9:53 proto: udp health_name: dns.quad9.net - addr: 149.112.112.112:53 proto: udp health_name: dns.quad9.net - addr: 1.1.1.1:53 proto: tls server_name: cloudflare-dns.com - addr: 9.9.9.9:853 proto: tls server_name: dns.quad9.net cache: enabled: true size: 200000 shards: 32 min_ttl: 0s max_ttl: 1h # Keep expired answers around this long so a dead upstream costs latency, # not availability. serve_stale: 30m prefetch: true negative_ttl: 30m persist: enabled: true path: data/cache.db interval: 30s max_entries: 500000 load_on_start: true prewarm: [] blocklist: enabled: true # nxdomain | zero | redirect | drop | refused default_action: nxdomain response_ip: 0.0.0.0 response_ipv6: "::" response_ttl: 60s # RPZ-style policy zones and/or local authoritative data, as master files. local_zones: [] # Inline rules. "*.example.com" covers subdomains, "**.example.com" covers # the apex too, a bare name matches only itself. block_entries: [] allow_entries: [] lists: - name: haas format: plain url: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts path: data/lists/hosts enabled: true refresh: 24h categories: [ads, tracking] - name: easylist format: adblock url: https://easylist.to/easylist/easylist.txt path: data/lists/easylist.txt enabled: false refresh: 24h categories: [ads] - name: local-rpz format: rpz path: zones/local.rpz.zone enabled: true refresh: 0s acl: # allow | deny | block_only default_policy: allow default_rate_limit: 0 groups: - name: guests comment: Blocklists apply, but the kitchen-sink allowlist does not. match: cidrs: ["192.168.90.0/24"] policy: block_only rate_limit: 50 - name: printers comment: No recursion at all; they only need DHCP. match: cidrs: ["192.168.91.0/24"] policy: deny qlog: enabled: true path: data/queries.db max_entries: 200000 flush_interval: 1s # 1.0 logs every query. Lower it on a busy instance: the per-domain # counters are what the dashboard actually needs. sample_rate: 1.0 log_blocked: true log_cached: false log_errors: true live_buffer: 2000 top_domains: 5000 top_ttl: 5m cluster: enabled: false # node_id: dns-1 # advertise: http://10.0.0.10:8080 peer_ttl: 15s valkey: addrs: ["valkey:6379"] prefix: fancydns pool_size: 10 dial_timeout: 2s read_timeout: 2s # Only the lease holder fetches lists, so N instances do not hit a # mirror N times. leader_ttl: 30s api: enabled: true listen: ["127.0.0.1:8080"] # tls_listen: ["0.0.0.0:8443"] base_path: /api ui: true allow_config_write: true allow_blocklist_write: true # Only these proxies may set X-Forwarded-For; anything else is ignored, so a # client cannot spoof its identity past the ACL or the rate limiter. trusted_proxies: [] cors_origins: [] auth: # none | apikey | basic mode: apikey api_keys: ["CHANGE-ME-long-random-string"] read_only_api_keys: [] trust_loopback: true session_ttl: 12h rate_limit: per_minute: 600 failures: 10 lockout: 5m metrics: enabled: true path: /metrics protect: true log: level: info format: text