From 16b9271cafc9370f902904c03cf4dd4f93ae2b5f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 23 Oct 2025 22:13:43 +0200 Subject: [PATCH] feat: add dns container with AGH + unbound --- .gitignore | 4 +- .../container_build.nix | 0 lxc/dns.nix | 41 ++++++++++ lxc/dns/adguardhome-config.nix | 74 +++++++++++++++++++ lxc/dns/logs-adguard.alloy.nix | 49 ++++++++++++ lxc/dns/logs-unbound.alloy.nix | 44 +++++++++++ 6 files changed, 210 insertions(+), 2 deletions(-) rename container_build.nix => lib/container_build.nix (100%) create mode 100644 lxc/dns.nix create mode 100644 lxc/dns/adguardhome-config.nix create mode 100644 lxc/dns/logs-adguard.alloy.nix create mode 100644 lxc/dns/logs-unbound.alloy.nix diff --git a/.gitignore b/.gitignore index 92d18e8..c035cc9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,5 @@ config.tf.json nixos-template # Possibly sensitive for public repo -infra/ips.nix -infra/constants.nix +lib/ips.nix +lib/constants.nix diff --git a/container_build.nix b/lib/container_build.nix similarity index 100% rename from container_build.nix rename to lib/container_build.nix diff --git a/lxc/dns.nix b/lxc/dns.nix new file mode 100644 index 0000000..1792333 --- /dev/null +++ b/lxc/dns.nix @@ -0,0 +1,41 @@ +{ + pkgs, + name, + containersMapping, + ... +}: +let + hostname = pkgs.lib.removeSuffix ".nix" name; + infra = import ../lib/constants.nix; + container_id = containersMapping.${hostname}; + ip = infra.build_ip container_id; + domainname = "${hostname}${infra.domains.internal}"; +in +{ + cores = 2; + memory = "2G"; + disk = "4G"; + swap = 512; + ports = [ + 80 + 53 + 12345 + ]; + exposed = false; + services = { + adguardhome = import ./dns/adguardhome-config.nix { inherit infra ip domainname; }; + unbound = { + enable = true; + }; + }; + logging.enable = true; + logging.metrics.enable = true; + etc."alloy/logs-adguard.alloy".text = + (import ./dns/logs-adguard.alloy.nix { + inherit ip domainname; + }).out; + etc."alloy/logs-unbound.alloy".text = + (import ./dns/logs-unbound.alloy.nix { + inherit ip domainname; + }).out; +} diff --git a/lxc/dns/adguardhome-config.nix b/lxc/dns/adguardhome-config.nix new file mode 100644 index 0000000..fa2dc1d --- /dev/null +++ b/lxc/dns/adguardhome-config.nix @@ -0,0 +1,74 @@ +{ + infra, + ip, + domainname, + ... +}: +{ + enable = true; + host = "0.0.0.0"; + port = 80; + openFirewall = true; + mutableSettings = true; + settings = { + http = { + address = "${ip}:80"; + session_ttl = "720h"; + }; + users = [ + { + name = infra.master_login; + password = infra.master_htpasswd; + } + ]; + 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; + } + ]; + + auth_attempts = 5; + block_auth_min = 15; + language = "fr"; + dns = { + bind_hosts = [ ip ]; + port = 53; + upstream_dns = [ + "127.0.0.1:5335" + "https://dns10.quad9.net/dns-query" + ]; + }; + filtering = { + safe_search = { + enabled = true; + bing = true; + duckduckgo = true; + ecosia = true; + google = true; + pixabay = true; + yandex = true; + youtube = true; + }; + rewrites = [ + { + domain = "*${infra.domains.exposed}"; + answer = infra.reverse_proxy_addr; + } + { + domain = domainname; + answer = ip; + } + # add internal domains for all containers? + ]; + }; + }; +} diff --git a/lxc/dns/logs-adguard.alloy.nix b/lxc/dns/logs-adguard.alloy.nix new file mode 100644 index 0000000..8fc1c41 --- /dev/null +++ b/lxc/dns/logs-adguard.alloy.nix @@ -0,0 +1,49 @@ +{ ip, domainname, ... }: +{ + out = '' + loki.relabel "agh_journal" { + forward_to = [] + rule { + source_labels = ["__journal__priority_keyword"] + target_label = "level" + } + rule { + source_labels = ["__journal__SYSLOG_IDENTIFIER"] + target_label = "app" + } + } + loki.source.journal "agh_journal_scrape" { + forward_to = [loki.process.agh_router.receiver] + matches = "_SYSTEMD_UNIT=adguardhome.service" + relabel_rules = loki.relabel.agh_journal.rules + labels = { + service = "adguardhome", + host = "${domainname}", + host_ip = "${ip}", + } + } + + loki.process "agh_router" { + stage.regex { + expression = "^(?P\\S+ \\S+) \\[(?P\\w+)\\] (?P.*)$" + } + + stage.timestamp { + source = "timestamp" + format = "2006-01-02 15:04:05" + } + + stage.labels { + values = { + level = "level", + } + } + + stage.output { + source = "message" + } + + forward_to = [loki.write.grafana_loki.receiver] + } + ''; +} diff --git a/lxc/dns/logs-unbound.alloy.nix b/lxc/dns/logs-unbound.alloy.nix new file mode 100644 index 0000000..7abf795 --- /dev/null +++ b/lxc/dns/logs-unbound.alloy.nix @@ -0,0 +1,44 @@ +{ ip, domainname, ... }: +{ + out = '' + loki.relabel "unbd_journal" { + forward_to = [] + rule { + source_labels = ["__journal__priority_keyword"] + target_label = "level" + } + rule { + source_labels = ["__journal__SYSLOG_IDENTIFIER"] + target_label = "app" + } + } + loki.source.journal "unbd_journal_scrape" { + forward_to = [loki.process.unbd_router.receiver] + matches = "_SYSTEMD_UNIT=unbound.service" + relabel_rules = loki.relabel.unbd_journal.rules + labels = { + service = "unbound", + host = "${domainname}", + host_ip = "${ip}", + } + } + + loki.process "unbound_router" { + stage.pattern { + pattern = "[<_>] : " + } + + stage.labels { + values = { + level = "level", + } + } + + stage.output { + source = "message" + } + + forward_to = [loki.write.grafana_loki.receiver] + } + ''; +}