pkgs/ap.nix: migrate template to nix

This commit is contained in:
Astro 2021-11-06 22:56:54 +01:00
parent 6329fda145
commit 40e8b351d5
4 changed files with 227 additions and 359 deletions

View File

@ -355,6 +355,23 @@ in
c3d2.type = "bridge";
bmx.type = "bridge";
};
ap4.links.switch-b2.ports = [ "wan" ];
ap6.links.switch-b2.ports = [ "wan" ];
ap21.links.switch-a1.ports = [ "lan" ];
ap27.links.switch-b2.ports = [ "wan" ];
ap28.links.switch-b2.ports = [ "wan" ];
ap32.links.switch-b2.ports = [ "lan" ];
ap33.links.switch-b2.ports = [ "lan" ];
ap36.links.switch-b2.ports = [ "wan" ];
ap43.links.switch-a1.ports = [ "wan" ];
ap44.links.switch-a1.ports = [ "lan" ];
ap45.links.switch-a1.ports = [ "lan" ];
ap46.links.switch-a1.ports = [ "lan" ];
ap47.links.switch-a1.ports = [ "lan" ];
ap48.links.switch-a1.ports = [ "lan" ];
ap49.links.switch-a1.ports = [ "lan" ];
ap50.links.switch-a1.ports = [ "lan" ];
ap52.links.switch-a1.ports = [ "lan" ];
}
# host priv*-gw settings
@ -443,14 +460,10 @@ in
in
if model ? ports
then
if model.ports == [ {
interface = "eth0";
port = "lan";
type = "phys";
} ] && builtins.length wanTargets > 0
if getPorts "wan" == [] && builtins.length wanTargets > 0
then {
# Only 1 Ethernet port, treat as uplink
"${builtins.head wanTargets}".ports = [ "eth0" ];
# Only 1 Ethernet port, treat lan as uplink
"${builtins.head wanTargets}".ports = getPorts "lan";
}
else
lib.optionalAttrs (builtins.length wanTargets > 0) {

View File

@ -456,6 +456,16 @@ let
config.site.net.${net}.vlan
) config.site.hosts.${hostName}.links.${name}.nets;
};
trunk = mkOption {
type = types.bool;
description = "Trunk with tagged VLANs?";
default =
if config.site.net ? ${name}
then false
else if config.site.hosts ? ${name}
then true
else throw "Invalid link target: \"${name}\"";
};
};
};
in

View File

@ -35,8 +35,10 @@ let
builtins.foldl' (result: interface:
if port != []
then result // {
type = "phys";
inherit interface port;
"${port}" = {
type = "phys";
inherit interface port;
};
}
else result
) {} (builtins.split "[[:space:]]+" arg);

View File

@ -8,21 +8,132 @@ let
while uci -q delete ${key}[-1]; do :; done
'';
uciNetworkMgmt = ifname: ''
set network.mgmt=interface
set network.mgmt.ifname=${ifname}
set network.mgmt.proto=static
set network.mgmt.ipaddr=${config.site.net.mgmt.hosts4.${hostName}}
set network.mgmt.netmask=${self.lib.netmasks.${elemAt (
builtins.split "/" config.site.net.mgmt.subnet4
) 2}}
set network.mgmt.gateway=${config.site.net.mgmt.hosts4."mgmt-gw"}
set network.mgmt.ip6addr=${config.site.net.mgmt.hosts6.dn42.${hostName}}
set network.mgmt.ip6gw=${config.site.net.mgmt.hosts6.dn42."mgmt-gw"}
delete network.mgmt.dns
add_list network.mgmt.dns={{ pillar['hosts-inet']['serv']['dnscache'] }}
add_list network.mgmt.dns={{ pillar['hosts-inet6']['dn42']['serv']['dnscache'] }}
'';
# hostBridgedNets =
# self.lib.unique (
# builtins.concatMap ({ ssids, ... }:
# map ({ net, ... }:
# net
# ) (builtins.attrValues ssids)
# ) (builtins.attrValues hostConfig.wifi)
# );
openwrtModel = self.lib.getOpenwrtModel hostConfig.model;
hasSwitch =
any ({ switch ? null, ... }: switch != null)
(builtins.attrValues openwrtModel.ports);
portsDoc =
let
portByIndex = builtins.foldl' (result: port:
let
key = if port ? index
then port.index
else if port ? interface
then port.interface
else "How to identify port ${lib.generators.toPretty {} port}?";
in result // {
"${key}" = port;
}
) {} (builtins.attrValues openwrtModel.ports);
in
concatMapStringsSep ", " (index:
"${index}:${
if portByIndex.${index} ? port
then portByIndex.${index}.port
else if portByIndex.${index} ? interface
then portByIndex.${index}.interface
else throw "What is port ${lib.generators.toPretty {} portByIndex.${index}.port}?"
}"
) (
builtins.sort builtins.lessThan (
builtins.attrNames portByIndex
)
);
switchHostInterface =
let
hostPorts = builtins.attrValues (
filterAttrs (_: { type, ... }: type == "host")
openwrtModel.ports
);
in if hostPorts == []
then throw "No host ports found for OpenWRT model ${hostConfig.model}"
else (builtins.head hostPorts).interface;
switchPortIndices = f:
map ({ index, ... }: index) (
builtins.attrValues (
filterAttrs (_: port: port ? index && f port)
openwrtModel.ports
)
);
trunked = map (index: "${index}t");
# OpenWRT switch ports string ("0t 1t 2 3 4") for a network (VLAN)
switchPortsConfig = net:
concatStringsSep " " (
# Host interface
trunked (switchPortIndices ({ interface ? null, ... }: interface == switchHostInterface))
++
# Access networks
optionals (hostConfig.links ? ${net}) (
builtins.concatMap (port':
switchPortIndices ({ port ? null, ... }: port == port')
) hostConfig.links.${net}.ports
)
++
# Trunk ports
builtins.concatMap (port':
trunked (switchPortIndices ({ port ? null, ... }: port == port'))
) (
builtins.concatMap ({ ports, ... }: ports) (
builtins.attrValues (
filterAttrs (_: { trunk, ... }:
trunk
) hostConfig.links
))
)
);
networkInterfaces = net:
let
inherit (config.site.net.${net}) vlan;
ifaces =
unique (
builtins.concatMap ({ trunk, ports, switch ? null, ... }:
builtins.concatMap (port:
builtins.concatMap (portData:
if portData ? port && port == portData.port
then [ ((
if portData ? switch
then switchHostInterface
else if portData ? interface
then portData.interface
else throw "Cannot find interface for ${port} on OpenWRT model ${hostConfig.model}"
) + (
if trunk || switch != null
then ".${toString vlan}"
else ""
)) ]
else []
) (builtins.attrValues openwrtModel.ports)
) ports
) (
builtins.attrValues (
filterAttrs (link: { nets, ... }:
link == net || builtins.elem net nets
) hostConfig.links
)
)
);
in
if ifaces == []
then throw "No interfaces found for ${net} on ${hostName}"
else ifaces;
in ''
#! ${pkgs.runtimeShell} -e
@ -36,350 +147,80 @@ in ''
"ash -e -x" <<__SSH__
''}
# Set root password
echo -e '${hostConfig.password}\n${hostConfig.password}' | passwd
# Set root password
echo -e '${hostConfig.password}\n${hostConfig.password}' | passwd
# add ssh pubkeys
${concatMapStrings (sshPubKey: ''
echo "${sshPubKey}" > /etc/dropbear/authorized_keys
'') config.site.sshPubKeys}
# add ssh pubkeys
${concatMapStrings (sshPubKey: ''
echo "${sshPubKey}" > /etc/dropbear/authorized_keys
'') config.site.sshPubKeys}
# System configuration
uci batch <<__UCI__
set system.@system[0].hostName=${hostName}
set dhcp.@dnsmasq[0].enabled=0
set system.@system[0].log_ip=${config.site.net.mgmt.hosts4.logging}
set system.@system[0].log_proto=udp
# System configuration
uci batch <<__UCI__
set system.@system[0].hostName=${hostName}
set dhcp.@dnsmasq[0].enabled=0
set system.@system[0].log_ip=${config.site.net.mgmt.hosts4.logging}
set system.@system[0].log_proto=udp
delete network.globals.ula_prefix
delete network.lan
delete network.wan
delete network.wan6
delete wireless.default_radio0
delete wireless.default_radio1
delete network.globals.ula_prefix
delete network.lan
delete network.wan
delete network.wan6
delete wireless.default_radio0
delete wireless.default_radio1
{%- set bridges = {} %}
{%- if conf.get('lan-access') %}
{%- do bridges.__setitem__(conf['lan-access'], True) %}
{%- endif %}
{%- for path, radio in conf['radios'].items() %}
{%- for ssid, ssidconf in radio['ssids'].items() %}
{%- do bridges.__setitem__(ssidconf['net'], True) %}
{%- endfor %}
{%- endfor %}
# Switch config
${optionalString hasSwitch ''
${uciDeleteAll "switch.@switch_vlan"}
{%- if conf['model'] == 'TL-WDR4300' %}
{# These models have a shared Ethernet chip for LAN/WAN and therefore need switching #}
set network.@switch[0]=switch
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=1
set network.@switch[0].name=switch0
set network.@switch_vlan[0]=switch_vlan
set network.@switch_vlan[0].device='switch0'
set network.@switch_vlan[0].vlan='1'
set network.@switch_vlan[0].ports='0t 1t'
set network.@switch_vlan[0].comment='mgmt'
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
set network.@switch_vlan[{{ switchnum }}].device='switch0'
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
{%- if conf.get('lan-access') == net %}
set network.@switch_vlan[{{ switchnum }}].ports='0t 1t 2 3 4 5'
{%- else %}
set network.@switch_vlan[{{ switchnum }}].ports='0t 1t'
{%- endif %}
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
{%- endfor %}
# Ports ${portsDoc}
${concatMapStrings (net: ''
add network switch_vlan
set network.@switch_vlan[-1]=switch_vlan
set network.@switch_vlan[-1].device='switch0'
set network.@switch_vlan[-1].vlan='${toString config.site.net.${net}.vlan}'
set network.@switch_vlan[-1].ports='${switchPortsConfig net}'
set network.@switch_vlan[-1].comment='${net}'
${uciNetworkMgmt "eth0.1"}
'') (
sort (net1: net2:
config.site.net.${net1}.vlan < config.site.net.${net2}.vlan
) (
unique (
builtins.concatMap ({ nets, ... }: nets)
(builtins.attrValues hostConfig.links)
)
)
)}
''}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
{%- endfor %}
# mgmt network
set network.mgmt=interface
set network.mgmt.ifname=${if builtins.length (networkInterfaces "mgmt") == 1 then builtins.head (networkInterfaces "mgmt") else throw "No interface for mgmt"}
set network.mgmt.proto=static
set network.mgmt.ipaddr=${config.site.net.mgmt.hosts4.${hostName}}
set network.mgmt.netmask=${self.lib.netmasks.${elemAt (
builtins.split "/" config.site.net.mgmt.subnet4
) 2}}
set network.mgmt.gateway=${config.site.net.mgmt.hosts4."mgmt-gw"}
set network.mgmt.ip6addr=${config.site.net.mgmt.hosts6.dn42.${hostName}}
set network.mgmt.ip6gw=${config.site.net.mgmt.hosts6.dn42."mgmt-gw"}
delete network.mgmt.dns
add_list network.mgmt.dns=${config.site.net.serv.hosts4.dnscache}
add_list network.mgmt.dns=${config.site.net.serv.hosts6.dn42.dnscache}
{%- elif conf['model'] == 'TL-WR1043ND' %}
{# These models have a shared Ethernet chip with separate CPU ports for LAN/WAN and therefore need switching #}
set network.@switch[0]=switch
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=1
set network.@switch[0].name=switch0
set network.@switch_vlan[0]=switch_vlan
set network.@switch_vlan[0].device='switch0'
set network.@switch_vlan[0].vlan='1'
set network.@switch_vlan[0].ports='5t 6t'
set network.@switch_vlan[0].comment='mgmt'
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
set network.@switch_vlan[{{ switchnum }}].device='switch0'
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
# 0: eth1; 1-4: LAN ports in reverse; 5: WAN port; 6: eth0
{%- if conf.get('lan-access') == net %}
set network.@switch_vlan[{{ switchnum }}].ports='0 1 2 3 4 5t'
{%- else %}
set network.@switch_vlan[{{ switchnum }}].ports='5t 6t'
{%- endif %}
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
{%- endfor %}
# bridged networks
${concatMapStrings (net:
let
iface = hostConfig.interfaces.${net};
in optionalString (net != "mgmt" && iface.type == "bridge") ''
set network.${net}=interface
set network.${net}.type=bridge
set network.${net}.proto=static
set network.${net}.ifname='${concatStringsSep " " (networkInterfaces net)}'
${uciNetworkMgmt "eth0.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
{%- if conf.get('lan-access') == net %}
set network.{{ net }}.ifname='eth1'
{%- else %}
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
{%- endif %}
{%- endfor %}
{%- elif conf['model'] == 'TL-Archer-C7v2' %}
{# These models have a shared Ethernet chip with separate CPU ports for LAN/WAN and therefore need switching #}
set network.@switch[0]=switch
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=1
set network.@switch[0].name=switch0
set network.@switch_vlan[0]=switch_vlan
set network.@switch_vlan[0].device='switch0'
set network.@switch_vlan[0].vlan='1'
set network.@switch_vlan[0].ports='1t 6t'
set network.@switch_vlan[0].comment='mgmt'
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
set network.@switch_vlan[{{ switchnum }}].device='switch0'
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
# 0: eth1; 1: WAN port; 2-5: LAN ports; 6: eth0
{%- if conf.get('lan-access') == net %}
set network.@switch_vlan[{{ switchnum }}].ports='0 1t 2 3 4 5'
{%- else %}
set network.@switch_vlan[{{ switchnum }}].ports='1t 6t'
{%- endif %}
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
{%- endfor %}
${uciNetworkMgmt "eth0.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
{%- if conf.get('lan-access') == net %}
set network.{{ net }}.ifname='eth1'
{%- else %}
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
{%- endif %}
{%- endfor %}
{%- elif conf['model'] == 'TL-Archer-C7v4' or conf['model'] == 'TL-Archer-C7v5' %}
set network.@switch[0]=switch
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=1
set network.@switch[0].name=switch0
set network.@switch_vlan[0]=switch_vlan
set network.@switch_vlan[0].device='switch0'
set network.@switch_vlan[0].vlan='1'
set network.@switch_vlan[0].ports='0t 1t'
set network.@switch_vlan[0].comment='mgmt'
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
set network.@switch_vlan[{{ switchnum }}].device='switch0'
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
# 0: eth0; 1: WAN port; 2-5: LAN ports
{%- if conf.get('lan-access') == net %}
set network.@switch_vlan[{{ switchnum }}].ports='0t 1t 2 3 4 5'
{%- else %}
set network.@switch_vlan[{{ switchnum }}].ports='0t 1t'
{%- endif %}
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
{%- endfor %}
${uciNetworkMgmt "eth0.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
{%- endfor %}
{%- elif conf['model'] == 'TL-WR1043NDv4' or conf['model'] == 'TL-WR1043NDv5' %}
set network.@switch[0]=switch
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=1
set network.@switch[0].name=switch0
set network.@switch_vlan[0]=switch_vlan
set network.@switch_vlan[0].device='switch0'
set network.@switch_vlan[0].vlan='1'
set network.@switch_vlan[0].ports='0t 5t'
set network.@switch_vlan[0].comment='mgmt'
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
set network.@switch_vlan[{{ switchnum }}].device='switch0'
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
# 0: eth0; 1-4: LAN ports; 5: WAN port
{%- if conf.get('lan-access') == net %}
set network.@switch_vlan[{{ switchnum }}].ports='0t 1 2 3 4 5t'
{%- else %}
set network.@switch_vlan[{{ switchnum }}].ports='0t 5t'
{%- endif %}
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
{%- endfor %}
${uciNetworkMgmt "eth0.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
{%- endfor %}
{%- elif conf['model'] == 'TL-WR841Nv8' %}
{# Like v9 but with eth0/1 switched #}
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=0
${uciNetworkMgmt "eth0.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
{# Add WAN VLAN to bridge #}
{%- set ports = ['eth0.' ~ pillar['vlans'][net]] %}
{# Add LAN ports to bridge #}
{%- if conf.get('lan-access') == net %}
{%- do ports.append('eth1') %}
{%- endif %}
set network.{{ net }}.ifname='{{ ' '.join(ports) }}'
{%- endfor %}
{%- elif conf['model'] == 'TL-WR740Nv4' %}
{# Separate eth0/1 interfaces for LAN/WAN #}
{# eth0 - Port 0: eth0, Port 2: LAN1, Port 3: LAN2, Port 4: LAN3, Port 1: LAN4 #}
{# eth1 - WAN #}
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=0
${uciNetworkMgmt "eth1.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
{# Add WAN VLAN to bridge #}
{%- set ports = ['eth1.' ~ pillar['vlans'][net]] %}
{# Add LAN ports to bridge #}
{%- if conf.get('lan-access') == net %}
{%- do ports.append('eth0') %}
{%- endif %}
set network.{{ net }}.ifname='{{ ' '.join(ports) }}'
{%- endfor %}
{%- elif conf['model'] == 'TL-WA901NDv3' or conf['model'] == 'Ubnt-UniFi-AP-AC-LR' %}
{# Only eth0 exists, no switch #}
${uciNetworkMgmt "eth0.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
{# Add WAN VLAN to bridge #}
set network.{{ net }}.ifname='{{ 'eth0.' ~ pillar['vlans'][net] }}'
{%- endfor %}
{%- elif conf['model'] == 'Ubnt-UAP-nanoHD' %}
{# no switch, eth0 exists but is not usable, using "lan" instead #}
${uciNetworkMgmt "lan.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
{# Add WAN VLAN to bridge #}
set network.{{ net }}.ifname='{{ 'lan.' ~ pillar['vlans'][net] }}'
{%- endfor %}
{%- elif conf['model'] == 'DIR-615H1' or conf['model'] == 'DIR-615D4' %}
{# All DIR-615 share the same port layout #}
delete network.lan_dev
delete network.wan_dev
{# switch is cpu port 6, wan:cpu port 4, lan port 1 is cpu port 3, lan port 2 is 2 etc #}
set network.@switch[0]=switch
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=1
set network.@switch[0].name=switch0
set network.@switch_vlan[0]=switch_vlan
set network.@switch_vlan[0].device='switch0'
set network.@switch_vlan[0].vlan='1'
set network.@switch_vlan[0].ports='4t 6t'
set network.@switch_vlan[0].comment='mgmt'
{%- for net, switchnum in zip(bridges.keys(), range(1, 999)) %}
set network.@switch_vlan[{{ switchnum }}]=switch_vlan
set network.@switch_vlan[{{ switchnum }}].device='switch0'
set network.@switch_vlan[{{ switchnum }}].vlan='{{ pillar['vlans'][net] }}'
{%- if conf.get('lan-access') == net %}
set network.@switch_vlan[{{ switchnum }}].ports='0 1 2 3 4t 6t'
{%- else %}
set network.@switch_vlan[{{ switchnum }}].ports='4t 6t'
{%- endif %}
set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}'
{%- endfor %}
${uciNetworkMgmt "eth0.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
#TODO: this should consider lan-access
set network.{{ net }}.ifname='eth0.{{ pillar['vlans'][net] }}'
{%- endfor %}
{%- else %}
{# All other models may have separate Ethernet chips for LAN/WAN #}
set network.@switch[0].reset=1
set network.@switch[0].enable=1
set network.@switch[0].enable_vlan=0
${uciNetworkMgmt "eth1.1"}
{%- for net in bridges.keys() %}
set network.{{ net }}=interface
set network.{{ net }}.type=bridge
set network.{{ net }}.proto=static
{# Add WAN VLAN to bridge #}
{%- set ports = ['eth1.' ~ pillar['vlans'][net]] %}
{# Add LAN ports to bridge #}
{%- if conf.get('lan-access') == net %}
{%- do ports.append('eth0') %}
{%- endif %}
set network.{{ net }}.ifname='{{ ' '.join(ports) }}'
{%- endfor %}
{%- endif %}
'') (builtins.attrNames hostConfig.interfaces)
}
${uciDeleteAll "wireless.@wifi"}
@ -399,6 +240,7 @@ set network.{{ net }}.ifname='{{ ' '.join(ports) }}'
set wireless.radio${toString index}.htmode=${radioConfig.htmode}
set wireless.radio${toString index}.noscan=1
delete wireless.radio${toString index}.disabled
${concatMapStrings (ssid:
let
ssidConfig = radioConfig.ssids.${ssid};
@ -419,6 +261,7 @@ set network.{{ net }}.ifname='{{ ' '.join(ports) }}'
set wireless.@wifi-iface[-1].encryption=none
delete wireless.@wifi-iface[-1].key
''}
''
) (builtins.attrNames radioConfig.ssids)}
'') (builtins.attrNames hostConfig.wifi))}