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: Sandro <sandro.jaeckel@gmail.com>
This commit is contained in:
Carl Richard Theodor Schneider 2023-01-04 18:32:27 +01:00
parent 40cdc211f3
commit 59207cc930
2 changed files with 84 additions and 1 deletions

View File

@ -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";

View File

@ -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")
'';
}