apiVersion: v1 kind: Namespace metadata: name: dns --- apiVersion: v1 kind: ConfigMap metadata: name: fancy-dns-config namespace: dns labels: app.kubernetes.io/name: fancy-dns data: config.yaml: | # Rendered by the deployment below; kept in a ConfigMap so a change is a # `kubectl apply` rather than a rebuild. server: max_concurrent: 2048 timeouts: upstream: 2s list_fetch: 60s dns: # Use high ports in the pod so the container needs no privileged-port # capability. Services expose the standard DNS ports to clients. udp: ["0.0.0.0:1053", "[::]:1053"] tcp: ["0.0.0.0:1053", "[::]:1053"] max_udp_size: 1232 dot: enabled: true listen: ["0.0.0.0:1853"] cert_file: /etc/fancy-dns/tls/tls.crt key_file: /etc/fancy-dns/tls/tls.key doh: enabled: true listen: ["0.0.0.0:8443"] cert_file: /etc/fancy-dns/tls/tls.crt key_file: /etc/fancy-dns/tls/tls.key base_path: /dns-query upstream: policy: parallel max_attempts: 3 healthcheck_interval: 30s servers: - addr: 9.9.9.9:53 proto: udp - 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 # Memory envelope. The container limit (1Gi, in the StatefulSet) is the # hard ceiling; this tells the process about it so the collector works to # a target instead of being OOM-killed. `limit` is the soft GOMEMLIMIT and # must be at or below the container limit; `reserve` covers what the Go # heap does not account for — goroutine stacks, runtime metadata, and the # mmapped cache snapshot and query log. # # The cache byte budget is derived (60% of limit - reserve) unless it is # set explicitly. cache.size below is an *entry count*, so this is what # actually bounds the cache's memory: 500k entries of a few hundred bytes # each is well past 384MiB, and the byte budget is what will bite first. memory: limit: 1GiB reserve: 256MiB cache_max_bytes: 384MiB cache: enabled: true size: 500000 max_ttl: 1h serve_stale: 30m persist: enabled: true path: /var/lib/fancy-dns/cache.db interval: 30s blocklist: enabled: true default_action: nxdomain managed_zones: /var/lib/fancy-dns/managed-zones local_zones: [/etc/fancy-dns/zones/*.zone] lists: - name: edge-router-x-address-overrides format: rpz path: /etc/fancy-dns/rpz/address-overrides.rpz enabled: true refresh: 0s - name: haas format: plain url: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts path: /var/lib/fancy-dns/lists/hosts enabled: true refresh: 24h categories: [ads, tracking] acl: default_policy: allow groups: [] qlog: enabled: true path: /var/lib/fancy-dns/queries.db max_entries: 200000 sample_rate: 1.0 log_blocked: true log_cached: false api: enabled: true listen: ["0.0.0.0:8080"] base_path: /api ui: true allow_config_write: false # The key comes from the environment (a Secret mounted into the pod), not # from this ConfigMap, so `kubectl get cm` never prints it. The loader # substitutes ${VAR} before parsing and *fails to start* if the variable # is unset, so a missing secret is a crash loop rather than an # unauthenticated console. auth: mode: oidc api_keys: ["${FANCYDNS_API_KEY}"] oidc_issuer: https://users.k6n.net oidc_audience: https://dns.k6n.net oidc_client_id: fancy-dns oidc_write_roles: [admin] trust_loopback: false metrics: enabled: true path: /metrics protect: true log: level: info format: json