Commit 59207cc9 authored by Carl Richard Theodor Schneider's avatar Carl Richard Theodor Schneider
Browse files

nixos/adguardhome: Add `allowDHCP` option



This option conditionally adds the `CAP_NET_RAW` capability to the service,
which is mandatory for enabling the integrated DHCP server.
It also adds another test case to validate that the DHCP server successfully
provides IP addresses to clients.

Co-authored-by: default avatarSandro <sandro.jaeckel@gmail.com>
parent 40cdc211
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -41,6 +41,20 @@ in
      '';
    };

    allowDHCP = mkOption {
      default = cfg.settings.dhcp.enabled or false;
      defaultText = literalExpression ''config.services.adguardhome.settings.dhcp.enabled or false'';
      type = bool;
      description = lib.mdDoc ''
        Allows AdGuard Home to open raw sockets (`CAP_NET_RAW`), which is
        required for the integrated DHCP server.

        The default enables this conditionally if the declarative configuration
        enables the integrated DHCP server. Manually setting this option is only
        required for non-declarative setups.
      '';
    };

    mutableSettings = mkOption {
      default = true;
      type = bool;
@@ -147,7 +161,7 @@ in
      serviceConfig = {
        DynamicUser = true;
        ExecStart = "${pkgs.adguardhome}/bin/adguardhome ${args}";
        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ] ++ optionals cfg.allowDHCP [ "CAP_NET_RAW" ];
        Restart = "always";
        RestartSec = 10;
        RuntimeDirectory = "AdGuardHome";
+69 −0
Original line number Diff line number Diff line
@@ -40,6 +40,67 @@
        };
      };
    };

    dhcpConf = { lib, ... }: {
      virtualisation.vlans = [ 1 ];

      networking = {
        # Configure static IP for DHCP server
        useDHCP = false;
        interfaces."eth1" = lib.mkForce {
          useDHCP = false;
          ipv4 = {
            addresses = [{
              address = "10.0.10.1";
              prefixLength = 24;
            }];

            routes = [{
              address = "10.0.10.0";
              prefixLength = 24;
            }];
          };
        };

        # Required for DHCP
        firewall.allowedUDPPorts = [ 67 68 ];
      };

      services.adguardhome = {
        enable = true;
        allowDHCP = true;
        mutableSettings = false;
        settings = {
          schema_version = 0;
          dns = {
            bind_host = "0.0.0.0";
            bootstrap_dns = "127.0.0.1";
          };
          dhcp = {
            # This implicitly enables CAP_NET_RAW
            enabled = true;
            interface_name = "eth1";
            local_domain_name = "lan";
            dhcpv4 = {
              gateway_ip = "10.0.10.1";
              range_start = "10.0.10.100";
              range_end = "10.0.10.101";
              subnet_mask = "255.255.255.0";
            };
          };
        };
      };
    };

    client = { lib, ... }: {
      virtualisation.vlans = [ 1 ];
      networking = {
        interfaces.eth1 = {
          useDHCP = true;
          ipv4.addresses = lib.mkForce [ ];
        };
      };
    };
  };

  testScript = ''
@@ -63,5 +124,13 @@
        mixedConf.systemctl("restart adguardhome.service")
        mixedConf.wait_for_unit("adguardhome.service")
        mixedConf.wait_for_open_port(3000)

    with subtest("Testing successful DHCP start"):
        dhcpConf.wait_for_unit("adguardhome.service")
        client.wait_for_unit("network-online.target")
        # Test IP assignment via DHCP
        dhcpConf.wait_until_succeeds("ping -c 5 10.0.10.100")
        # Test hostname resolution over DHCP-provided DNS
        dhcpConf.wait_until_succeeds("ping -c 5 client.lan")
  '';
}