From a40ec7d1f370973bc167ddd7adf256d9b73e533d Mon Sep 17 00:00:00 2001 From: Erwin Boskma Date: Wed, 7 Jun 2023 08:34:16 +0200 Subject: [PATCH] valkyrie: Standalone AdGuard Home container --- machines/default.nix | 9 + machines/valkyrie/.terraform.lock.hcl | 23 ++ machines/valkyrie/configuration.nix | 45 +++ machines/valkyrie/main.tf | 37 +++ machines/valkyrie/variables.tf | 17 ++ modules/adguard/default.nix | 393 ++++++++++++++++++++++++++ modules/unbound/default.nix | 78 +++++ 7 files changed, 602 insertions(+) create mode 100644 machines/valkyrie/.terraform.lock.hcl create mode 100644 machines/valkyrie/configuration.nix create mode 100644 machines/valkyrie/main.tf create mode 100644 machines/valkyrie/variables.tf create mode 100644 modules/adguard/default.nix create mode 100644 modules/unbound/default.nix diff --git a/machines/default.nix b/machines/default.nix index 5d9af1e..ee274f7 100644 --- a/machines/default.nix +++ b/machines/default.nix @@ -76,4 +76,13 @@ inputs: { substituteOnTarget = true; }; }; + valkyrie = { + config = import ./valkyrie/configuration.nix inputs; + deploy = { + host = "10.0.0.206"; + sshUser = "erwin"; + buildOn = "local"; + substituteOnTarget = true; + }; + }; } diff --git a/machines/valkyrie/.terraform.lock.hcl b/machines/valkyrie/.terraform.lock.hcl new file mode 100644 index 0000000..6003b17 --- /dev/null +++ b/machines/valkyrie/.terraform.lock.hcl @@ -0,0 +1,23 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/telmate/proxmox" { + version = "2.9.14" + hashes = [ + "h1:H/f+LbVyPOLslHLAYnGuMMRqWFZ65K6E3V+MCYgfAyk=", + "zh:0d049d33f705e5b814d30028770c084151218439424e99684ce31d7e26a720b5", + "zh:20b1c64ed56d81de95f3f37b82b45b4654c0de26670c0e87a474c5cce13cd015", + "zh:2946058abd1d8e50e475b9ec39781eb02576b40dbd80f4653fade4493a4514c6", + "zh:29e50a25c456f040ce072f23ac57b5b82ebd3b916ca5ae6688332b5ec62adc4a", + "zh:3612932306ce5f08db94868f526cbb8c56d0d3c6ebe1c11a83f92bbf94354296", + "zh:42d1699b0abebaac82ea5a19f4393541d8bb2741bde204a8ac1028cdc29d1b14", + "zh:5ffd5dc567262eb8aafdf2f6eac63f7f21361da9c5d75a3c36b479638a0001b0", + "zh:6692ef323e3b89de99934ad731f6a1850525bf8142916ae28ea4e4048d73a787", + "zh:a5afc98e9a4038516bb58e788cb77dea67a60dce780dfcd206d7373c5a56b776", + "zh:bf902cded709d84fa27fbf91b589c241f2238a6c4924e4e479eebd74320b93a5", + "zh:cab0e1e72c9cebcf669fc6f35ec28cb8ab2dffb0237afc8860aa40d23bf8a49f", + "zh:e523b99a48beec83d9bc04b2d336266044f9f53514cefb652fe6768611847196", + "zh:f593915e8a24829d322d2eaeedcb153328cf9042f0d84f66040dde1be70ede04", + "zh:fba1aff541133e2129dfda0160369635ab48503d5c44b8407ce5922ecc15d0bd", + ] +} diff --git a/machines/valkyrie/configuration.nix b/machines/valkyrie/configuration.nix new file mode 100644 index 0000000..22399e3 --- /dev/null +++ b/machines/valkyrie/configuration.nix @@ -0,0 +1,45 @@ +{ self, ... }: +{ modulesPath, ... }: { + imports = [ + (modulesPath + "/virtualisation/proxmox-lxc.nix") + + ../../users/root + ../../users/erwin + ]; + + eboskma = { + users.erwin = { + enable = true; + server = true; + }; + adguard = { + enable = true; + upstreams = [ + "127.0.0.1:5335" + ]; + }; + nix-common = { + enable = true; + remote-builders = true; + }; + unbound.enable = true; + }; + + services.resolved.extraConfig = '' + DNSStubListener=no + ''; + + time.timeZone = "Europe/Amsterdam"; + + system.configurationRevision = self.inputs.nixpkgs.lib.mkIf (self ? rev) self.rev; + + proxmoxLXC = { + privileged = true; + }; + + security.sudo.execWheelOnly = true; + + services.tailscale.enable = true; + + system.stateVersion = "23.11"; +} diff --git a/machines/valkyrie/main.tf b/machines/valkyrie/main.tf new file mode 100644 index 0000000..6ccbf5a --- /dev/null +++ b/machines/valkyrie/main.tf @@ -0,0 +1,37 @@ +terraform { + required_providers { + proxmox = { + source = "Telmate/proxmox" + } + } +} + +provider "proxmox" { + pm_api_url = var.proxmox_api_url + pm_api_token_id = var.proxmox_token_id + pm_api_token_secret = var.proxmox_token_secret + pm_tls_insecure = true +} + +resource "proxmox_lxc" "valkyrie" { + target_node = "pve" + hostname = "valkyrie" + ostemplate = "loki:vztmpl/nixos-23.11-default_20230606_amd64.tar.xz" + unprivileged = false + onboot = true + + memory = 2048 + swap = 2048 + + rootfs { + storage = "local-lvm" + size = "32G" + } + + network { + name = "eth0" + bridge = "vmbr0" + ip = "10.0.0.206/24" + gw = "10.0.0.1" + } +} diff --git a/machines/valkyrie/variables.tf b/machines/valkyrie/variables.tf new file mode 100644 index 0000000..e974186 --- /dev/null +++ b/machines/valkyrie/variables.tf @@ -0,0 +1,17 @@ +variable "proxmox_token_id" { + description = "Proxmox API token ID" + type = string + sensitive = true +} + +variable "proxmox_token_secret" { + description = "Proxmox API token secret" + type = string + sensitive = true +} + +variable "proxmox_api_url" { + description = "Proxmox API URL" + type = string + sensitive = true +} diff --git a/modules/adguard/default.nix b/modules/adguard/default.nix new file mode 100644 index 0000000..bd61349 --- /dev/null +++ b/modules/adguard/default.nix @@ -0,0 +1,393 @@ +{ config +, lib +, ... +}: +with lib; let + cfg = config.eboskma.adguard; +in +{ + options.eboskma.adguard = { + enable = mkEnableOption "adguard"; + upstreams = mkOption { + description = "Upstream DNS servers"; + type = types.listOf types.str; + example = [ + "http://1.1.1.1" + "tls://1.1.1.1" + "1.1.1.1" + ]; + }; + }; + + config = mkIf cfg.enable { + services.adguardhome = { + enable = true; + openFirewall = true; + + settings = { + auth_attempts = 5; + block_auth_min = 15; + + clients = { + persistent = [ + { + blocked_services = [ ]; + filtering_enabled = false; + ids = [ "10.0.0.81" ]; + ignore_querylog = false; + ignore_statistics = false; + name = "TV"; + parental_enabled = false; + safe_search = { + bing = false; + duckduckgo = false; + enabled = false; + google = false; + pixabay = false; + yandex = false; + youtube = false; + }; + safebrowsing_enabled = false; + tags = [ "device_tv" ]; + upstreams = [ "1.1.1.1" ]; + use_global_blocked_services = true; + use_global_settings = true; + } + { + blocked_services = [ + "9gag" + "amazon" + "cloudflare" + "dailymotion" + "discord" + "disneyplus" + "ebay" + "epic_games" + "facebook" + "hulu" + "imgur" + "instagram" + "mail_ru" + "netflix" + "ok" + "origin" + "pinterest" + "qq" + "reddit" + "skype" + "snapchat" + "spotify" + "steam" + "telegram" + "tiktok" + "tinder" + "twitch" + "twitter" + "viber" + "vimeo" + "vk" + "wechat" + "weibo" + "whatsapp" + "youtube" + ]; + filtering_enabled = true; + ids = [ "5a:b6:23:35:1c:76" ]; + ignore_querylog = false; + ignore_statistics = false; + name = "xiaomi-fan"; + parental_enabled = true; + safe_search = { + bing = false; + duckduckgo = false; + enabled = false; + google = false; + pixabay = false; + yandex = false; + youtube = false; + }; + safebrowsing_enabled = true; + tags = [ "device_other" ]; + upstreams = [ ]; + use_global_blocked_services = false; + use_global_settings = true; + } + ]; + runtime_sources = { + arp = true; + dhcp = true; + hosts = true; + rdns = true; + whois = true; + }; + }; + debug_pprof = false; + dhcp = { + dhcpv4 = { + gateway_ip = "10.0.0.1"; + icmp_timeout_msec = 1000; + lease_duration = 86400; + options = [ ]; + range_end = "10.0.0.200"; + range_start = "10.0.0.150"; + subnet_mask = "255.255.255.0"; + }; + dhcpv6 = { + lease_duration = 86400; + ra_allow_slaac = false; + ra_slaac_only = false; + range_start = ""; + }; + interface_name = "eth0"; + enabled = true; + local_domain_name = "lan"; + }; + dns = { + aaaa_disabled = false; + all_servers = true; + allowed_clients = [ ]; + anonymize_client_ip = false; + bind_hosts = [ "0.0.0.0" ]; + blocked_hosts = [ "version.bind" "id.server" "hostname.bind" ]; + blocked_response_ttl = 10; + blocked_services = [ "vk" "mail_ru" "pinterest" "tinder" "wechat" "ok" "qq" "snapchat" "weibo" "9gag" ]; + blocking_ipv4 = ""; + blocking_ipv6 = ""; + blocking_mode = "default"; + bogus_nxdomain = [ ]; + bootstrap_dns = [ ]; + bootstrap_prefer_ipv6 = false; + cache_optimistic = false; + cache_size = 4194304; + cache_time = 30; + cache_ttl_max = 0; + cache_ttl_min = 0; + disallowed_clients = [ ]; + dns64_prefixes = [ ]; + edns_client_subnet = { + custom_ip = ""; + enabled = true; + use_custom = false; + }; + enable_dnssec = true; + fastest_addr = false; + fastest_timeout = "1s"; + filtering_enabled = true; + filters_update_interval = 24; + handle_ddr = true; + ipset = [ ]; + ipset_file = ""; + local_ptr_upstreams = [ ]; + max_goroutines = 0; + parental_block_host = "family-block.dns.adguard.com"; + parental_cache_size = 1048576; + parental_enabled = false; + port = 53; + private_networks = [ ]; + protection_disabled_until = null; + protection_enabled = true; + ratelimit = 20; + ratelimit_whitelist = [ ]; + refuse_any = true; + rewrites = [ + { + answer = "10.0.0.254"; + domain = "track.datarift.nl"; + } + { + answer = "10.0.0.2"; + domain = "ca.datarift.nl"; + } + { + answer = "10.0.0.252"; + domain = "pve.datarift.nl"; + } + { + answer = "10.0.0.251"; + domain = "git.datarift.nl"; + } + { + answer = "10.0.0.251"; + domain = "minio.datarift.nl"; + } + { + answer = "10.0.0.251"; + domain = "home.datarift.nl"; + } + { + answer = "10.0.0.251"; + domain = "drone.datarift.nl"; + } + { + answer = "10.0.0.100"; + domain = "vidz.datarift.nl"; + } + { + answer = "10.0.0.4"; + domain = "loki.datarift.nl"; + } + { + answer = "10.0.0.251"; + domain = "minio-admin.datarift.nl"; + } + { + answer = "192.168.4.32"; + domain = "vaultserver.horus.nu"; + } + { + answer = "10.0.0.254"; + domain = "mqtt.datarift.nl"; + } + { + answer = "10.0.0.251"; + domain = "frigate.datarift.nl"; + } + { + answer = "192.168.4.130"; + domain = "containers.internal.horus.nu"; + } + { + answer = "192.168.4.121"; + domain = "repohost.bedum.horus.nu"; + } + { + answer = "192.168.4.150"; + domain = "teamcity.horus.nu"; + } + { + answer = "2a02:a441:c959:1:52ef:4c5d:ffac:25bc"; + domain = "frigate.datarift.nl"; + } + ]; + safe_search = { + bing = true; + duckduckgo = true; + enabled = false; + google = true; + pixabay = true; + yandex = true; + youtube = true; + }; + safebrowsing_block_host = "standard-block.dns.adguard.com"; + safebrowsing_cache_size = 1048576; + safebrowsing_enabled = false; + safesearch_cache_size = 1048576; + serve_http3 = false; + trusted_proxies = [ "127.0.0.0/8" "::1/128" ]; + upstream_dns = cfg.upstreams; + upstream_dns_file = ""; + upstream_timeout = "10s"; + use_dns64 = false; + use_http3_upstreams = false; + use_private_ptr_resolvers = true; + }; + filters = [ + { + enabled = true; + id = 1; + name = "AdGuard DNS filter"; + url = "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt"; + } + { + enabled = true; + id = 2; + name = "AdAway"; + url = "https://adaway.org/hosts.txt"; + } + { + enabled = true; + id = 3; + name = "hpHosts - Ad and Tracking servers only"; + url = "https://hosts-file.net/ad_servers.txt"; + } + { + enabled = true; + id = 4; + name = "MalwareDomainList.com Hosts List"; + url = "https://www.malwaredomainlist.com/hostslist/hosts.txt"; + } + { + enabled = true; + id = 1586463155; + name = "dbl.oisd.nl"; + url = "https://dbl.oisd.nl/"; + } + ]; + http_proxy = ""; + language = ""; + log_compress = false; + log_file = ""; + log_localtime = false; + log_max_age = 3; + log_max_backups = 0; + log_max_size = 100; + os = { + group = ""; + rlimit_nofile = 0; + user = ""; + }; + querylog = { + enabled = true; + file_enabled = true; + ignored = [ ]; + interval = "168h"; + size_memory = 1000; + }; + schema_version = 20; + statistics = { + enabled = true; + ignored = [ ]; + interval = "168h"; + }; + theme = "auto"; + tls = { + allow_unencrypted_doh = false; + certificate_chain = ""; + certificate_path = ""; + dnscrypt_config_file = ""; + enabled = false; + force_https = false; + port_dns_over_quic = 784; + port_dns_over_tls = 853; + port_dnscrypt = 0; + port_https = 443; + private_key = ""; + private_key_path = ""; + server_name = ""; + strict_sni_check = false; + }; + user_rules = [ + "@@||msmetrics.ws.sonos.com^$important" + "@@||trafficdeposit.com^$important" + "@@||omropfryslan.bbvms.com^$important" + "@@||cdn.riverhit.com^$important" + "@@||kpngroup.emsecure.net^$important" + "@@||chtbl.com^$important" + "@@||*^$client='TV'" + "||mozilla.cloudflare-dns.com^$important" + "||use-application-dns.net^$important" + "@@||widget.fitanalytics.com^$important" + "@@||cdn.bluebillywig.com^$important" + "@@||bert.org^$important" + "||prod-pre.fns.tunein.com^$important" + "#||mi.com^$dnsrewrite=NOERROR;A;10.0.0.4" + "#||xiaomi.com^$dnsrewrite=NOERROR;A;10.0.0.4" + "@@||aa.tweakers.nl^$important" + "@@||ab.tweakers.nl^$important" + "||zip^" + ]; + users = [ ]; + verbose = false; + web_session_ttl = 720; + whitelist_filters = [ ]; + }; + }; + + # This is necessary to bind a raw socket for DHCP + systemd.services.adguardhome.serviceConfig.AmbientCapabilities = [ "CAP_NET_RAW" ]; + + networking.firewall = { + allowedUDPPorts = [ 53 67 ]; + }; + }; +} diff --git a/modules/unbound/default.nix b/modules/unbound/default.nix new file mode 100644 index 0000000..c6ef692 --- /dev/null +++ b/modules/unbound/default.nix @@ -0,0 +1,78 @@ +{ config, lib, ... }: +with lib; +let + cfg = config.eboskma.unbound; +in +{ + options.eboskma.unbound = { enable = mkEnableOption "unbound DNS"; }; + + config = mkIf cfg.enable { + services.unbound = { + enable = true; + localControlSocketPath = "/run/unbound/unbound.ctl"; + settings = { + server = { + # Setting logfile to an empty string outputs to stderr + log-queries = false; + verbosity = 1; + + port = 5335; + do-ip4 = true; + do-ip6 = true; + do-udp = true; + do-tcp = true; + prefer-ip6 = true; + + hide-identity = true; + hide-version = true; + + # Trust glue only if it is within the server's authority + harden-glue = true; + + # Require DNSSEC data for trust-anchored zones, if such data is absent, the zone becomes BOGUS + harden-dnssec-stripped = true; + + harden-referral-path = true; + + # Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes + # see https://discourse.pi-hole.net/t/unbound-stubby-or-dnscrypt-proxy/9378 for further details + use-caps-for-id = false; + + # Reduce EDNS reassembly buffer size. + # Suggested by the unbound man page to reduce fragmentation reassembly problems + edns-buffer-size = 1472; + + # Perform prefetching of close to expired message cache entries + # This only applies to domains that have been frequently queried + prefetch = true; + prefetch-key = true; + + # This attempts to reduce latency by serving the outdated record before + # updating it instead of the other way around. Alternative is to increase + # cache-min-ttl to e.g. 3600. + cache-min-ttl = 0; + serve-expired = true; + + rrset-cache-size = "256m"; + msg-cache-size = "128m"; + msg-cache-slabs = 4; + # One thread should be sufficient, can be increased on beefy machines. In reality for most users running on small networks or on a single machine, it should be unnecessary to seek performance enhancement by increasing num-threads above 1. + num-threads = 2; + + # Ensure kernel buffer is large enough to not lose messages in traffic spikes + so-rcvbuf = "1m"; + + # Ensure privacy of local IP ranges + private-address = [ + "192.168.0.0/16" + "169.254.0.0/16" + "172.16.0.0/12" + "10.0.0.0/8" + "fd00::/8" + "fe80::/10" + ]; + }; + }; + }; + }; +}