22# hostapd.nix
33#
44
5- { config , pkgs , ... } :
5+ #
6+ # NOT using service.hostapd, because it has limited configuration capabilities
7+ # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/hostapd.nix
8+ #
9+ # Using custom systemd services to run hostapd per interface
10+ #
11+ # systemctl status hostapd-wlp35s0
12+ # systemctl status hostapd-wlp65s0
13+ # systemctl status hostapd-wlp70s0
14+ #
15+ # nix pkgs source
16+ # https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ho/hostapd/package.nix
17+ # https://w1.fi/hostapd/
18+ # https://github.com/latelee/hostapd
19+ #
20+ # Giant NixPkgs PR: https://github.com/NixOS/nixpkgs/pull/222536
21+ #
22+ #
23+ { config , pkgs , lib , ... } :
624
725let
8- interface1 = "wlp35s0" ; # e.g. 2.4GHz channel 6
9- interface2 = "wlp65s0" ; # e.g. 5GHz channel 100
10- interface3 = "wlp70s0" ; # e.g. 5GHz channel 149
26+ radios = {
27+ wlp35s0 = {
28+ channel = 6 ;
29+ hwMode = "g" ;
30+ } ;
31+ wlp65s0 = {
32+ channel = 100 ;
33+ hwMode = "a" ;
34+ } ;
35+ wlp70s0 = {
36+ channel = 149 ;
37+ hwMode = "a" ;
38+ } ;
39+ } ;
1140
12- commonHostapdSettings = ''
13- ssid=myssid
14- wpa=2
15- wpa_key_mgmt=SAE
16- rsn_pairwise=CCMP
17- sae_require_mfp=1
18- ieee80211w=2
19- ieee80211n=1
20- ieee80211ac=1
21- ieee80211ax=1
22- wmm_enabled=1
41+ mkHostapdConf = iface : cfg :
2342
24- # WMM tuning for Best Effort (AC_BE)
25- wmm_ac_be_aifs=1
26- wmm_ac_be_cwmin=4
27- wmm_ac_be_cwmax=4
28- wmm_ac_be_txop_limit=32
29- wmm_ac_be_acm=0
43+ pkgs . writeText "hostapd-${ iface } .conf" ''
44+ driver=nl80211
45+ ssid=myssid
46+ hw_mode=${ cfg . hwMode }
47+ channel=${ toString cfg . channel }
48+ ctrl_interface=/run/hostapd-${ iface }
49+ ctrl_interface_group=0
3050
31- # 802.11r (Fast BSS Transition)
32- ieee80211r=1
33- mobility_domain=4f57
34- ft_over_ds=1
35- ft_psk_generate_local=1
36- nas_identifier=myssid-ap
37- '' ;
38- in
39- {
40- services . hostapd = {
41- enable = true ;
42- radios = {
43- "${ interface1 } " = {
44- config = pkgs . writeText "hostapd-1.conf" ( ''
45- interface=${ interface1 }
46- hw_mode=g
47- channel=6
48- ${ commonHostapdSettings }
49- '' ) ;
50- } ;
51- "${ interface2 } " = {
52- config = pkgs . writeText "hostapd-2.conf" ( ''
53- interface=${ interface2 }
54- hw_mode=a
55- channel=100
56- ${ commonHostapdSettings }
57- '' ) ;
58- } ;
59- "${ interface3 } " = {
60- config = pkgs . writeText "hostapd-3.conf" ( ''
61- interface=${ interface3 }
62- hw_mode=a
63- channel=149
64- ${ commonHostapdSettings }
65- '' ) ;
66- } ;
67- } ;
68- } ;
51+ # WPA3 (SAE) configuration
52+ wpa=2
53+ wpa_key_mgmt=SAE
54+ rsn_pairwise=CCMP
55+ sae_require_mfp=1
56+ ieee80211w=2
57+ wpa_passphrase=mysecurepassword
6958
70- # Disable DHCP on all interfaces, use static IP or bridge later
71- networking . interfaces . ${ interface1 } . useDHCP = false ;
72- networking . interfaces . ${ interface2 } . useDHCP = false ;
73- networking . interfaces . ${ interface3 } . useDHCP = false ;
59+ # Enable 802.11n/ac/ax
60+ ieee80211n=1
61+ ieee80211ac=1
62+ ieee80211ax=1
7463
75- networking . interfaces . ${ interface1 } . ipv4 . addresses = [ { address = "192.168.30.1" ; prefixLength = 24 ; } ] ;
76- networking . interfaces . ${ interface2 } . ipv4 . addresses = [ { address = "192.168.31.1" ; prefixLength = 24 ; } ] ;
77- networking . interfaces . ${ interface3 } . ipv4 . addresses = [ { address = "192.168.32.1" ; prefixLength = 24 ; } ] ;
64+ wmm_enabled=1
7865
79- networking . firewall . enable = true ;
80- networking . nat . enable = true ;
81- networking . nat . externalInterface = "enp1s0" ;
66+ # Optional WMM tuning
67+ wmm_ac_be_aifs=1
68+ wmm_ac_be_cwmin=4
69+ wmm_ac_be_cwmax=4
70+ wmm_ac_be_txop_limit=32
71+ wmm_ac_be_acm=0
72+ '' ;
73+
74+ hostapdConfigs = lib . mapAttrs ( iface : cfg : mkHostapdConf iface cfg ) radios ;
75+
76+ in {
77+ systemd . services = lib . mapAttrs' ( iface : confPath : {
78+ name = "hostapd-${ iface } " ;
79+ value = {
80+ description = "Hostapd on ${ iface } " ;
81+ wantedBy = [ "multi-user.target" ] ;
82+ after = [ "network.target" ] ;
83+ serviceConfig = {
84+ ExecStart = "${ pkgs . hostapd } /bin/hostapd -i ${ iface } ${ confPath } " ;
85+ Restart = "on-failure" ;
86+ RuntimeDirectory = "hostapd-${ iface } " ;
87+ } ;
88+ } ;
89+ } ) hostapdConfigs ;
8290}
91+
92+ # end
0 commit comments