# AdGuard Home — household DNS with ad blocking, local resolution, DoH via dns.nook.family, and DoT via dot.nook.family:853 resource "kubernetes_namespace" "dns" { metadata { name = "dns" labels = { managed-by = "terraform" tier = "infrastructure" } } } resource "kubernetes_persistent_volume_claim" "adguard_config" { wait_until_bound = false metadata { name = "adguard-config" namespace = kubernetes_namespace.dns.metadata[0].name } spec { access_modes = ["ReadWriteOnce"] resources { requests = { storage = "1Gi" } } } } resource "kubernetes_persistent_volume_claim" "adguard_data" { wait_until_bound = false metadata { name = "adguard-data" namespace = kubernetes_namespace.dns.metadata[0].name } spec { access_modes = ["ReadWriteOnce"] resources { requests = { storage = "5Gi" } } } } # Desired AdGuard settings — applied by init container on every pod start. # To change DNS upstreams, filter lists, or rewrites: edit here, terraform apply, then push apps/adguard.yaml. resource "kubernetes_config_map" "adguard_defaults" { metadata { name = "adguard-defaults" namespace = kubernetes_namespace.dns.metadata[0].name } data = { "AdGuardHome.yaml" = <<-EOT dns: bind_hosts: - 0.0.0.0 port: 53 upstream_dns: - https://dns.cloudflare.com/dns-query - https://dns.google/dns-query bootstrap_dns: - 1.1.1.1 - 8.8.8.8 - 9.9.9.10 - 149.112.112.10 upstream_mode: load_balance cache_enabled: true cache_size: 4194304 filters: - enabled: true url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt name: AdGuard DNS filter id: 1 - enabled: true url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt name: AdAway Default Blocklist id: 2 - enabled: true url: https://big.oisd.nl/domainswild name: OISD Big id: 3 - enabled: true url: https://easylist.to/easylist/easylist.txt name: EasyList id: 4 - enabled: true url: https://easylist.to/easylist/easyprivacy.txt name: EasyPrivacy id: 5 tls: enabled: true server_name: dot.nook.family port_dns_over_tls: 853 certificate_path: /etc/adguard/tls/tls.crt private_key_path: /etc/adguard/tls/tls.key allow_unencrypted_doh: true filtering: filtering_enabled: true rewrites: - domain: '*.nook.family' answer: ${var.legion_ip} enabled: true - domain: '*.neuralplatform.ai' answer: ${var.legion_ip} enabled: true EOT } } # TLS certificate for DoT — issued via cert-manager DNS-01 (Cloudflare) resource "kubernetes_manifest" "adguard_dot_cert" { manifest = { apiVersion = "cert-manager.io/v1" kind = "Certificate" metadata = { name = "adguard-dot-tls" namespace = kubernetes_namespace.dns.metadata[0].name } spec = { secretName = "adguard-dot-tls" issuerRef = { name = "letsencrypt-prod" kind = "ClusterIssuer" } dnsNames = ["dot.nook.family"] } } depends_on = [kubernetes_manifest.cluster_issuer_prod] } # Deployment + Service managed by Argo CD — see servers/legion/apps/adguard.yaml resource "kubernetes_ingress_v1" "adguard" { metadata { name = "adguard" namespace = kubernetes_namespace.dns.metadata[0].name annotations = { "traefik.ingress.kubernetes.io/router.entrypoints" = "websecure" "cert-manager.io/cluster-issuer" = "letsencrypt-prod" } } spec { tls { hosts = ["dns.nook.family"] secret_name = "adguard-tls" } rule { host = "dns.nook.family" http { path { path = "/" path_type = "Prefix" backend { service { name = "adguard-ui" port { number = 3000 } } } } } } } depends_on = [helm_release.cert_manager] } # Host-level bootstrap notes (run bootstrap.sh once on new Legion installs): # - systemd-resolved disabled (conflicts with AdGuard on port 53) # - k3s config.yaml includes tls-san for LAN IP # - /etc/resolv.conf set to 1.1.1.1 fallback # See: servers/legion/bootstrap.sh