176 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { config, lib, pkgs, ... }:
 | |
| 
 | |
| # TODO:
 | |
| #
 | |
| # asserts
 | |
| #   ensure that the nl80211 module is loaded/compiled in the kernel
 | |
| #   wpa_supplicant and hostapd on the same wireless interface doesn't make any sense
 | |
| 
 | |
| with lib;
 | |
| 
 | |
| let
 | |
| 
 | |
|   cfg = config.services.hostapd;
 | |
| 
 | |
|   configFile = pkgs.writeText "hostapd.conf" ''
 | |
|     interface=${cfg.interface}
 | |
|     driver=${cfg.driver}
 | |
|     ssid=${cfg.ssid}
 | |
|     hw_mode=${cfg.hwMode}
 | |
|     channel=${toString cfg.channel}
 | |
| 
 | |
|     # logging (debug level)
 | |
|     logger_syslog=-1
 | |
|     logger_syslog_level=2
 | |
|     logger_stdout=-1
 | |
|     logger_stdout_level=2
 | |
| 
 | |
|     ctrl_interface=/var/run/hostapd
 | |
|     ctrl_interface_group=${cfg.group}
 | |
| 
 | |
|     ${if cfg.wpa then ''
 | |
|       wpa=1
 | |
|       wpa_passphrase=${cfg.wpaPassphrase}
 | |
|       '' else ""}
 | |
| 
 | |
|     ${cfg.extraConfig}
 | |
|   '' ;
 | |
| 
 | |
| in
 | |
| 
 | |
| {
 | |
|   ###### interface
 | |
| 
 | |
|   options = {
 | |
| 
 | |
|     services.hostapd = {
 | |
| 
 | |
|       enable = mkOption {
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Enable putting a wireless interface into infrastructure mode,
 | |
|           allowing other wireless devices to associate with the wireless
 | |
|           interface and do wireless networking. A simple access point will
 | |
|           <option>enable hostapd.wpa</option>,
 | |
|           <option>hostapd.wpaPassphrase</option>, and
 | |
|           <option>hostapd.ssid</option>, as well as DHCP on the wireless
 | |
|           interface to provide IP addresses to the associated stations, and
 | |
|           NAT (from the wireless interface to an upstream interface).
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       interface = mkOption {
 | |
|         default = "";
 | |
|         example = "wlp2s0";
 | |
|         description = ''
 | |
|           The interfaces <command>hostapd</command> will use.
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       driver = mkOption {
 | |
|         default = "nl80211";
 | |
|         example = "hostapd";
 | |
|         type = types.string;
 | |
|         description = ''
 | |
|           Which driver <command>hostapd</command> will use.
 | |
|           Most applications will probably use the default.
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       ssid = mkOption {
 | |
|         default = "nixos";
 | |
|         example = "mySpecialSSID";
 | |
|         type = types.string;
 | |
|         description = "SSID to be used in IEEE 802.11 management frames.";
 | |
|       };
 | |
| 
 | |
|       hwMode = mkOption {
 | |
|         default = "g";
 | |
|         type = types.enum [ "a" "b" "g" ];
 | |
|         description = ''
 | |
|           Operation mode.
 | |
|           (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g).
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       channel = mkOption {
 | |
|         default = 7;
 | |
|         example = 11;
 | |
|         type = types.int;
 | |
|         description = ''
 | |
|           Channel number (IEEE 802.11)
 | |
|           Please note that some drivers do not use this value from
 | |
|           <command>hostapd</command> and the channel will need to be configured
 | |
|           separately with <command>iwconfig</command>.
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       group = mkOption {
 | |
|         default = "wheel";
 | |
|         example = "network";
 | |
|         type = types.string;
 | |
|         description = ''
 | |
|           Members of this group can control <command>hostapd</command>.
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       wpa = mkOption {
 | |
|         default = true;
 | |
|         description = ''
 | |
|           Enable WPA (IEEE 802.11i/D3.0) to authenticate with the access point.
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       wpaPassphrase = mkOption {
 | |
|         default = "my_sekret";
 | |
|         example = "any_64_char_string";
 | |
|         type = types.string;
 | |
|         description = ''
 | |
|           WPA-PSK (pre-shared-key) passphrase. Clients will need this
 | |
|           passphrase to associate with this access point.
 | |
|           Warning: This passphrase will get put into a world-readable file in
 | |
|           the Nix store!
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       extraConfig = mkOption {
 | |
|         default = "";
 | |
|         example = ''
 | |
|           auth_algo=0
 | |
|           ieee80211n=1
 | |
|           ht_capab=[HT40-][SHORT-GI-40][DSSS_CCK-40]
 | |
|           '';
 | |
|         type = types.lines;
 | |
|         description = "Extra configuration options to put in hostapd.conf.";
 | |
|       };
 | |
|     };
 | |
|   };
 | |
| 
 | |
| 
 | |
|   ###### implementation
 | |
| 
 | |
|   config = mkIf cfg.enable {
 | |
| 
 | |
|     assertions = [
 | |
|       { assertion = (cfg.channel >= 1 && cfg.channel <= 13);
 | |
|         message = "channel must be between 1 and 13";
 | |
|       }];
 | |
| 
 | |
|     environment.systemPackages =  [ pkgs.hostapd ];
 | |
| 
 | |
|     systemd.services.hostapd =
 | |
|       { description = "hostapd wireless AP";
 | |
| 
 | |
|         path = [ pkgs.hostapd ];
 | |
|         wantedBy = [ "network.target" ];
 | |
| 
 | |
|         after = [ "${cfg.interface}-cfg.service" "nat.service" "bind.service" "dhcpd.service"];
 | |
| 
 | |
|         serviceConfig =
 | |
|           { ExecStart = "${pkgs.hostapd}/bin/hostapd ${configFile}";
 | |
|             Restart = "always";
 | |
|           };
 | |
|       };
 | |
|   };
 | |
| }
 | 
