151 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { config, lib, pkgs, ... }:
 | |
| 
 | |
| with lib;
 | |
| 
 | |
| let
 | |
| 
 | |
|   cfg = config.services.dhcpd;
 | |
| 
 | |
|   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"
 | |
|     ''
 | |
|       default-lease-time 600;
 | |
|       max-lease-time 7200;
 | |
|       authoritative;
 | |
|       ddns-update-style interim;
 | |
|       log-facility local1; # see dhcpd.nix
 | |
| 
 | |
|       ${cfg.extraConfig}
 | |
| 
 | |
|       ${lib.concatMapStrings
 | |
|           (machine: ''
 | |
|             host ${machine.hostName} {
 | |
|               hardware ethernet ${machine.ethernetAddress};
 | |
|               fixed-address ${machine.ipAddress};
 | |
|             }
 | |
|           '')
 | |
|           cfg.machines
 | |
|       }
 | |
|     '';
 | |
| 
 | |
| in
 | |
| 
 | |
| {
 | |
| 
 | |
|   ###### interface
 | |
| 
 | |
|   options = {
 | |
| 
 | |
|     services.dhcpd = {
 | |
| 
 | |
|       enable = mkOption {
 | |
|         default = false;
 | |
|         description = "
 | |
|           Whether to enable the DHCP server.
 | |
|         ";
 | |
|       };
 | |
| 
 | |
|       extraConfig = mkOption {
 | |
|         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 here, such as the options specifying the subnet
 | |
|           mask, DNS servers, etc.
 | |
|         ";
 | |
|       };
 | |
| 
 | |
|       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.
 | |
|         ";
 | |
|       };
 | |
| 
 | |
|       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.
 | |
|         ";
 | |
|       };
 | |
| 
 | |
|     };
 | |
| 
 | |
|   };
 | |
| 
 | |
| 
 | |
|   ###### implementation
 | |
| 
 | |
|   config = mkIf config.services.dhcpd.enable {
 | |
| 
 | |
|     users = {
 | |
|       extraUsers.dhcpd = {
 | |
|         uid = config.ids.uids.dhcpd;
 | |
|         description = "DHCP daemon user";
 | |
|       };
 | |
|     };
 | |
| 
 | |
|     systemd.services.dhcpd =
 | |
|       { description = "DHCP server";
 | |
| 
 | |
|         wantedBy = [ "multi-user.target" ];
 | |
| 
 | |
|         after = [ "network.target" ];
 | |
| 
 | |
|         path = [ pkgs.dhcp ];
 | |
| 
 | |
|         preStart =
 | |
|           ''
 | |
|             mkdir -m 755 -p ${stateDir}
 | |
| 
 | |
|             touch ${stateDir}/dhcpd.leases
 | |
| 
 | |
|             mkdir -m 755 -p /run/dhcpd
 | |
|             chown dhcpd /run/dhcpd
 | |
|           '';
 | |
| 
 | |
|         serviceConfig =
 | |
|           { ExecStart = "@${pkgs.dhcp}/sbin/dhcpd dhcpd"
 | |
|               + " -pf /run/dhcpd/dhcpd.pid -cf ${configFile}"
 | |
|               + " -lf ${stateDir}/dhcpd.leases -user dhcpd -group nogroup"
 | |
|               + " ${toString cfg.interfaces}";
 | |
|             Restart = "always";
 | |
|             Type = "forking";
 | |
|             PIDFile = "/run/dhcpd/dhcpd.pid";
 | |
|           };
 | |
|       };
 | |
| 
 | |
|   };
 | |
| 
 | |
| }
 | 
