diff options
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/modules/rename.nix | 3 | ||||
-rw-r--r-- | nixos/modules/services/networking/dhcpd.nix | 250 |
2 files changed, 152 insertions, 101 deletions
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index 758f229d59d78..ad1ba86980d5e 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -164,6 +164,9 @@ with lib; else { addr = value inetAddr; port = value inetPort; } )) + # dhcpd + (mkRenamedOptionModule [ "services" "dhcpd" ] [ "services" "dhcpd4" ]) + # Options that are obsolete and have no replacement. (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "") (mkRemovedOptionModule [ "programs" "bash" "enable" ] "") diff --git a/nixos/modules/services/networking/dhcpd.nix b/nixos/modules/services/networking/dhcpd.nix index d2cd00e74a1f0..86bcaa96f3454 100644 --- a/nixos/modules/services/networking/dhcpd.nix +++ b/nixos/modules/services/networking/dhcpd.nix @@ -4,11 +4,10 @@ with lib; let - cfg = config.services.dhcpd; + cfg4 = config.services.dhcpd4; + cfg6 = config.services.dhcpd6; - stateDir = "/var/lib/dhcp"; # Don't use /var/state/dhcp; not FHS-compliant. - - configFile = if cfg.configFile != null then cfg.configFile else pkgs.writeText "dhcpd.conf" + writeConfig = cfg: pkgs.writeText "dhcpd.conf" '' default-lease-time 600; max-lease-time 7200; @@ -29,131 +28,180 @@ let } ''; -in - -{ - - ###### interface - - options = { + dhcpdService = postfix: cfg: optionalAttrs cfg.enable { + "dhcpd${postfix}" = { + description = "DHCPv${postfix} server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + preStart = '' + mkdir -m 755 -p ${cfg.stateDir} + touch ${cfg.stateDir}/dhcpd.leases + ''; + + serviceConfig = + let + configFile = if cfg.configFile != null then cfg.configFile else writeConfig cfg; + args = [ "@${pkgs.dhcp}/sbin/dhcpd" "dhcpd${postfix}" "-${postfix}" + "-pf" "/run/dhcpd${postfix}/dhcpd.pid" + "-cf" "${configFile}" + "-lf" "${cfg.stateDir}/dhcpd.leases" + "-user" "dhcpd" "-group" "nogroup" + ] ++ cfg.extraFlags + ++ cfg.interfaces; + + in { + ExecStart = concatMapStringsSep " " escapeShellArg args; + Type = "forking"; + Restart = "always"; + RuntimeDirectory = [ "dhcpd${postfix}" ]; + PIDFile = "/run/dhcpd${postfix}/dhcpd.pid"; + }; + }; + }; - services.dhcpd = { + machineOpts = {...}: { + config = { - enable = mkOption { - default = false; - description = " - Whether to enable the DHCP server. - "; + hostName = mkOption { + type = types.str; + example = "foo"; + description = '' + Hostname which is assigned statically to the machine. + ''; }; - extraConfig = mkOption { - type = types.lines; - default = ""; - example = '' - option subnet-mask 255.255.255.0; - option broadcast-address 192.168.1.255; - option routers 192.168.1.5; - option domain-name-servers 130.161.158.4, 130.161.33.17, 130.161.180.1; - option domain-name "example.org"; - subnet 192.168.1.0 netmask 255.255.255.0 { - range 192.168.1.100 192.168.1.200; - } + ethernetAddress = mkOption { + type = types.str; + example = "00:16:76:9a:32:1d"; + description = '' + MAC address of the machine. ''; - description = " - Extra text to be appended to the DHCP server configuration - file. Currently, you almost certainly need to specify - something here, such as the options specifying the subnet - mask, DNS servers, etc. - "; }; - extraFlags = mkOption { - default = ""; - example = "-6"; - description = " - Additional command line flags to be passed to the dhcpd daemon. - "; + ipAddress = mkOption { + type = types.str; + example = "192.168.1.10"; + description = '' + IP address of the machine. + ''; }; - configFile = mkOption { - default = null; - description = " - The path of the DHCP server configuration file. If no file - is specified, a file is generated using the other options. - "; - }; + }; + }; - interfaces = mkOption { - default = ["eth0"]; - description = " - The interfaces on which the DHCP server should listen. - "; - }; + dhcpConfig = postfix: { - machines = mkOption { - default = []; - example = [ - { hostName = "foo"; - ethernetAddress = "00:16:76:9a:32:1d"; - ipAddress = "192.168.1.10"; - } - { hostName = "bar"; - ethernetAddress = "00:19:d1:1d:c4:9a"; - ipAddress = "192.168.1.11"; - } - ]; - description = " - A list mapping ethernet addresses to IP addresses for the - DHCP server. - "; - }; + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable the DHCPv${postfix} server. + ''; + }; + stateDir = mkOption { + type = types.path; + # We use /var/lib/dhcp for DHCPv4 to save backwards compatibility. + default = "/var/lib/dhcp${if postfix == "4" then "" else postfix}"; + description = '' + State directory for the DHCP server. + ''; }; - }; + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + option subnet-mask 255.255.255.0; + option broadcast-address 192.168.1.255; + option routers 192.168.1.5; + option domain-name-servers 130.161.158.4, 130.161.33.17, 130.161.180.1; + option domain-name "example.org"; + subnet 192.168.1.0 netmask 255.255.255.0 { + range 192.168.1.100 192.168.1.200; + } + ''; + description = '' + Extra text to be appended to the DHCP server configuration + file. Currently, you almost certainly need to specify something + there, such as the options specifying the subnet mask, DNS servers, + etc. + ''; + }; + extraFlags = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Additional command line flags to be passed to the dhcpd daemon. + ''; + }; - ###### implementation + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + The path of the DHCP server configuration file. If no file + is specified, a file is generated using the other options. + ''; + }; - config = mkIf config.services.dhcpd.enable { + interfaces = mkOption { + type = types.listOf types.str; + default = ["eth0"]; + description = '' + The interfaces on which the DHCP server should listen. + ''; + }; - users = { - extraUsers.dhcpd = { - uid = config.ids.uids.dhcpd; - description = "DHCP daemon user"; - }; + machines = mkOption { + type = types.listOf (types.submodule machineOpts); + default = []; + example = [ + { hostName = "foo"; + ethernetAddress = "00:16:76:9a:32:1d"; + ipAddress = "192.168.1.10"; + } + { hostName = "bar"; + ethernetAddress = "00:19:d1:1d:c4:9a"; + ipAddress = "192.168.1.11"; + } + ]; + description = '' + A list mapping Ethernet addresses to IPv${postfix} addresses for the + DHCP server. + ''; }; - systemd.services.dhcpd = - { description = "DHCP server"; + }; + +in + +{ + + ###### interface - wantedBy = [ "multi-user.target" ]; + options = { - after = [ "network.target" ]; + services.dhcpd4 = dhcpConfig "4"; + services.dhcpd6 = dhcpConfig "6"; - path = [ pkgs.dhcp ]; + }; - preStart = - '' - mkdir -m 755 -p ${stateDir} - touch ${stateDir}/dhcpd.leases + ###### implementation - mkdir -m 755 -p /run/dhcpd - chown dhcpd /run/dhcpd - ''; + config = mkIf (cfg4.enable || cfg6.enable) { - serviceConfig = - { ExecStart = "@${pkgs.dhcp}/sbin/dhcpd dhcpd" - + " -pf /run/dhcpd/dhcpd.pid -cf ${configFile}" - + " -lf ${stateDir}/dhcpd.leases -user dhcpd -group nogroup" - + " ${cfg.extraFlags}" - + " ${toString cfg.interfaces}"; - Restart = "always"; - Type = "forking"; - PIDFile = "/run/dhcpd/dhcpd.pid"; - }; + users = { + extraUsers.dhcpd = { + uid = config.ids.uids.dhcpd; + description = "DHCP daemon user"; }; + }; + + systemd.services = dhcpdService "4" cfg4 // dhcpdService "6" cfg6; }; |