226 lines
5.9 KiB
YAML
226 lines
5.9 KiB
YAML
# 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
|
|
|
|
# The memory envelope. A cgroup kill is an outage; a cache miss is not, so the
|
|
# runtime gets a soft ceiling to work towards instead of finding out the hard
|
|
# way. Set limit to your container's memory limit, minus the reserve.
|
|
memory:
|
|
# Soft heap ceiling (GOMEMLIMIT). 0 = unbounded. The Go heap excludes
|
|
# goroutine stacks, runtime metadata and the bbolt mmap for the cache
|
|
# snapshot and the query log, which is what the reserve is for.
|
|
limit: "0"
|
|
reserve: "256MiB"
|
|
# Byte budget for the in-memory LRU. 0 derives it from the limit (60%).
|
|
# cache.size alone does not bound memory: one cached ANY or TXT answer can
|
|
# be tens of kilobytes, so 500k entries is anywhere from 150MB to several GB
|
|
# depending on what the traffic asked for.
|
|
cache_max_bytes: "0"
|
|
|
|
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 | oidc
|
|
mode: apikey
|
|
api_keys: ["CHANGE-ME-long-random-string"]
|
|
read_only_api_keys: []
|
|
trust_loopback: true
|
|
session_ttl: 12h
|
|
# For mode: oidc, configure a registered public PKCE client and the API
|
|
# audience included in its access tokens. Users need the admin role to write.
|
|
oidc_issuer: https://users.k6n.net
|
|
oidc_audience: https://fancy-dns.example.net
|
|
oidc_client_id: fancy-dns
|
|
oidc_write_roles: [admin]
|
|
rate_limit:
|
|
per_minute: 600
|
|
failures: 10
|
|
lockout: 5m
|
|
|
|
metrics:
|
|
enabled: true
|
|
path: /metrics
|
|
protect: true
|
|
|
|
log:
|
|
level: info
|
|
format: text
|