From d19d535d851eedc73a56f562e7cdf652f43891ca Mon Sep 17 00:00:00 2001 From: Leyla Becker Date: Mon, 20 Oct 2025 20:01:07 -0500 Subject: [PATCH] fix: made crab-hole dns accessible from other devices --- .../nixos/defiant/configuration.nix | 2 +- .../server/crab-hole/crab-hole.nix | 44 +++++++++++++++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/configurations/nixos/defiant/configuration.nix b/configurations/nixos/defiant/configuration.nix index c2b8fc5..fdf7356 100644 --- a/configurations/nixos/defiant/configuration.nix +++ b/configurations/nixos/defiant/configuration.nix @@ -348,7 +348,7 @@ openFirewall = true; show_doc = true; downstreams = { - loopback = { + host = { enable = true; openFirewall = true; }; diff --git a/modules/nixos-modules/server/crab-hole/crab-hole.nix b/modules/nixos-modules/server/crab-hole/crab-hole.nix index 58ff660..bde1d76 100644 --- a/modules/nixos-modules/server/crab-hole/crab-hole.nix +++ b/modules/nixos-modules/server/crab-hole/crab-hole.nix @@ -27,9 +27,19 @@ in { show_doc = lib.mkEnableOption "OpenAPI documentation (loads content from third party websites)"; downstreams = { - loopback = { - enable = lib.mkEnableOption "loopback downstream DNS server on localhost:53"; - openFirewall = lib.mkEnableOption "automatic port forwarding for the loopback downstream"; + host = { + enable = lib.mkEnableOption "host downstream DNS server accessible from network on all interfaces"; + port = lib.mkOption { + type = lib.types.port; + default = 53; + description = "Port for the host downstream DNS server to listen on."; + }; + openFirewall = lib.mkEnableOption "automatic port forwarding for the host downstream"; + disableSystemdResolved = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether to automatically disable systemd-resolved when using port 53. Set to false if you want to handle the conflict manually."; + }; }; }; @@ -82,6 +92,24 @@ in { }; config = lib.mkIf cfg.enable { + # Assertions for proper configuration + assertions = [ + { + assertion = !(cfg.downstreams.host.enable && cfg.downstreams.host.port == 53 && config.services.resolved.enable && cfg.downstreams.host.disableSystemdResolved); + message = "crab-hole host downstream cannot use port 53 while systemd-resolved is enabled. Either disable systemd-resolved or use a different port."; + } + { + assertion = !(cfg.downstreams.host.enable && cfg.downstreams.host.port == 53 && !cfg.downstreams.host.disableSystemdResolved && config.services.resolved.enable); + message = "crab-hole host downstream is configured to use port 53 but systemd-resolved is still enabled and disableSystemdResolved is false. Set disableSystemdResolved = true or manually disable systemd-resolved."; + } + ]; + + # Automatically disable systemd-resolved if using port 53 + services.resolved.enable = lib.mkIf (cfg.downstreams.host.enable && cfg.downstreams.host.port == 53 && cfg.downstreams.host.disableSystemdResolved) (lib.mkForce false); + + # Configure DNS nameservers when disabling systemd-resolved + networking.nameservers = lib.mkIf (cfg.downstreams.host.enable && cfg.downstreams.host.port == 53 && cfg.downstreams.host.disableSystemdResolved) (lib.mkDefault ["127.0.0.1" "1.1.1.1" "8.8.8.8"]); + services.crab-hole.settings = lib.mkMerge [ { api = { @@ -92,12 +120,12 @@ in { downstream = cfg.extraDownstreams; upstream.name_servers = cfg.extraUpstreams; } - (lib.mkIf cfg.downstreams.loopback.enable { + (lib.mkIf cfg.downstreams.host.enable { downstream = [ { protocol = "udp"; - listen = "localhost"; - port = 53; + listen = "0.0.0.0"; + port = cfg.downstreams.host.port; } ]; }) @@ -136,8 +164,8 @@ in { (lib.mkIf cfg.openFirewall { allowedTCPPorts = [cfg.port]; }) - (lib.mkIf (cfg.downstreams.loopback.enable && cfg.downstreams.loopback.openFirewall) { - allowedUDPPorts = [53]; + (lib.mkIf (cfg.downstreams.host.enable && cfg.downstreams.host.openFirewall) { + allowedUDPPorts = [cfg.downstreams.host.port]; }) ]; };