Ryan Lahfa
d29deeae56
To deal with mass rebuild disk space requirements, we can just levitate. In the future, we will use levitation as a general-purpose mechanism for partition layout migration, etc. Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
259 lines
6.9 KiB
Nix
259 lines
6.9 KiB
Nix
{
|
|
config,
|
|
pkgs,
|
|
modulesPath,
|
|
...
|
|
}:
|
|
let
|
|
inherit (pkgs.liminix.services) oneshot;
|
|
inherit (pkgs.pseudofile) symlink dir;
|
|
inherit (pkgs) serviceFns;
|
|
svc = config.system.service;
|
|
secrets-1 = {
|
|
ssid = "DGNum 2G prototype (N)";
|
|
};
|
|
secrets-2 = {
|
|
ssid = "DGNum 5G prototype (AX)";
|
|
};
|
|
baseParams = {
|
|
country_code = "FR";
|
|
hw_mode = "g";
|
|
channel = 6;
|
|
wmm_enabled = 1;
|
|
ieee80211n = 1;
|
|
ht_capab = "[LDPC][GF][HT40-][HT40+][SHORT-GI-40][MAX-AMSDU-7935][TX-STBC]";
|
|
auth_algs = 1;
|
|
wpa = 2;
|
|
wpa_pairwise = "TKIP CCMP";
|
|
rsn_pairwise = "CCMP";
|
|
};
|
|
|
|
radiusKeyMgmt = {
|
|
wpa_key_mgmt = "WPA-EAP";
|
|
};
|
|
|
|
modernParams = {
|
|
hw_mode = "a";
|
|
he_su_beamformer = 1;
|
|
he_su_beamformee = 1;
|
|
he_mu_beamformer = 1;
|
|
preamble = 1;
|
|
# Allow radar detection.
|
|
ieee80211d = 1;
|
|
ieee80211h = 1;
|
|
ieee80211ac = 1;
|
|
ieee80211ax = 1;
|
|
vht_capab = "[MAX-MPDU-7991][SU-BEAMFORMEE][SU-BEAMFORMER][RXLDPC][SHORT-GI-80][MAX-A-MPDU-LEN-EXP3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][TX-STBC-2BY1][RX-STBC-1][MU-BEAMFORMER]";
|
|
vht_oper_chwidth = 1;
|
|
he_oper_chwidth = 1;
|
|
channel = 36;
|
|
vht_oper_centr_freq_seg0_idx = 42;
|
|
he_oper_centr_freq_seg0_idx = 42;
|
|
require_vht = 1;
|
|
};
|
|
|
|
clientRadius = {
|
|
ieee8021x = 1;
|
|
eapol_version = 2;
|
|
use_pae_group_addr = 1;
|
|
dynamic_vlan = 0;
|
|
vlan_tagged_interface = "lan";
|
|
};
|
|
|
|
externalRadius = {
|
|
# TODO: when we have proper IPAM, set the right value here.
|
|
own_ip_addr = "127.0.0.1";
|
|
nas_identifier = "ap01.dgnum.eu";
|
|
|
|
# No DNS here, hostapd do not support this mode.
|
|
auth_server_addr = "129.199.195.129";
|
|
auth_server_port = 1812;
|
|
auth_server_shared_secret = "read it online";
|
|
};
|
|
|
|
mkWifiSta =
|
|
params: interface: secrets:
|
|
svc.hostapd.build {
|
|
inherit interface;
|
|
package = pkgs.hostapd-radius;
|
|
params = params // secrets;
|
|
dependencies = [ config.services.jitter ];
|
|
};
|
|
in
|
|
rec {
|
|
imports = [
|
|
"${modulesPath}/wlan.nix"
|
|
"${modulesPath}/network"
|
|
"${modulesPath}/dhcp6c"
|
|
"${modulesPath}/hostapd"
|
|
"${modulesPath}/ssh"
|
|
"${modulesPath}/ntp"
|
|
"${modulesPath}/vlan"
|
|
"${modulesPath}/bridge"
|
|
"${modulesPath}/jitter-rng"
|
|
"${modulesPath}/pki"
|
|
"${modulesPath}/ubus"
|
|
../../modules/dgn-access-control.nix
|
|
# TODO: god that's so a fucking hack.
|
|
(import "${modulesPath}/../devices/zyxel-nwa50ax").module
|
|
];
|
|
|
|
hostname = "ap01-prototype";
|
|
|
|
# Get moar random please
|
|
services.jitter = svc.jitter-rng.build { };
|
|
services.ubus = svc.ubus.build { };
|
|
|
|
# SSH keys are handled by the access control module.
|
|
dgn-access-control.enable = true;
|
|
users.root = {
|
|
passwd = "$6$jVXFFOp8HBYmgINR$lutB4kvw.W1jlXRby9ZYAgBitQ32RxQdYAGN.s2x4ris8J07vM6tzlRBQoeLELOIEMClDzbciQV0itfHQnTqd1";
|
|
};
|
|
|
|
services.int = svc.bridge.primary.build {
|
|
ifname = "int";
|
|
macAddressFromInterface = config.hardware.networkInterfaces.lan;
|
|
};
|
|
|
|
services.bridge = svc.bridge.members.build {
|
|
primary = services.int;
|
|
members = {
|
|
lan.member = config.hardware.networkInterfaces.lan;
|
|
wlan0 = {
|
|
member = config.hardware.networkInterfaces.wlan0;
|
|
# Bridge only once hostapd is ready.
|
|
dependencies = [ config.services.hostap-1-ready ];
|
|
};
|
|
wlan1 = {
|
|
member = config.hardware.networkInterfaces.wlan1;
|
|
# Bridge only once hostapd is ready.
|
|
dependencies = [ config.services.hostap-2-ready ];
|
|
};
|
|
};
|
|
};
|
|
|
|
services.resolvconf = oneshot rec {
|
|
name = "resolvconf";
|
|
up = ''
|
|
. ${serviceFns}
|
|
( in_outputs ${name}
|
|
for i in $(output ${services.dhcpv4} dns); do
|
|
echo "nameserver $i" >> resolv.conf
|
|
done
|
|
)
|
|
'';
|
|
|
|
dependencies = [
|
|
config.services.dhcpv4
|
|
];
|
|
};
|
|
|
|
filesystem = dir {
|
|
etc = dir {
|
|
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
|
|
"nixpkgs.version" = {
|
|
type = "f";
|
|
file = "${pkgs.lib.version}";
|
|
mode = "0444";
|
|
};
|
|
};
|
|
};
|
|
|
|
services.dhcpv4 = svc.network.dhcp.client.build {
|
|
interface = config.services.int;
|
|
dependencies = [
|
|
config.services.hostname
|
|
config.services.bridge.components.lan
|
|
];
|
|
};
|
|
|
|
# TODO(raito): these won't work with RAs
|
|
# fix them in Liminix directly and re-enable.
|
|
# services.dhcpv6 = svc.dhcp6c.client.build {
|
|
# interface = config.services.int;
|
|
# dependencies = [
|
|
# config.services.hostname
|
|
# config.services.bridge
|
|
# ];
|
|
# };
|
|
|
|
# services.ipv6 = svc.dhcp6c.address.build {
|
|
# interface = config.services.int;
|
|
# client = config.services.dhcpv6;
|
|
# dependencies = [ config.services.hostname ];
|
|
# };
|
|
|
|
services.defaultroute4 = svc.network.route.build {
|
|
via = "$(output ${services.dhcpv4} router)";
|
|
target = "default";
|
|
dependencies = [ services.dhcpv4 ];
|
|
};
|
|
|
|
services.packet_forwarding = svc.network.forward.build { };
|
|
services.sshd = svc.ssh.build { allowRoot = true; };
|
|
|
|
services.ntp = config.system.service.ntp.build {
|
|
pools = {
|
|
"pool.ntp.org" = [ "iburst" ];
|
|
};
|
|
|
|
dependencies = [ config.services.jitter ];
|
|
};
|
|
|
|
boot.tftp = {
|
|
serverip = "192.0.2.10";
|
|
ipaddr = "192.0.2.12";
|
|
};
|
|
|
|
# wlan0 is the 2.4GHz interface.
|
|
services.hostap-1 = mkWifiSta (
|
|
baseParams // radiusKeyMgmt
|
|
) config.hardware.networkInterfaces.wlan0 secrets-1;
|
|
services.hostap-1-ready = svc.hostapd-ready.build {
|
|
interface = config.hardware.networkInterfaces.wlan0;
|
|
};
|
|
# wlan1 is the 5GHz interface, e.g. AX capable.
|
|
services.hostap-2 = mkWifiSta (
|
|
baseParams // clientRadius // externalRadius // radiusKeyMgmt // modernParams
|
|
) config.hardware.networkInterfaces.wlan1 secrets-2;
|
|
# Oneshot that waits until the hostapd has set the interface in operational state.
|
|
services.hostap-2-ready = svc.hostapd-ready.build {
|
|
interface = config.hardware.networkInterfaces.wlan1;
|
|
};
|
|
|
|
defaultProfile.packages = with pkgs; [
|
|
zyxel-bootconfig
|
|
min-collect-garbage
|
|
iwinfo
|
|
ifwait
|
|
# Levitate enable us to mass-reinstall the system on the fly.
|
|
(levitate.override {
|
|
config = {
|
|
imports = [
|
|
"${modulesPath}/network"
|
|
"${modulesPath}/ssh"
|
|
"${modulesPath}/hardware.nix"
|
|
"${modulesPath}/kernel"
|
|
"${modulesPath}/outputs/tftpboot.nix"
|
|
"${modulesPath}/outputs.nix"
|
|
];
|
|
services = {
|
|
# Simplest DHCPv4 we can find.
|
|
dhcpv4 = svc.network.dhcp.client.build {
|
|
interface = config.hardware.networkInterfaces.lan;
|
|
};
|
|
inherit (config.services) sshd;
|
|
defaultroute4 = svc.network.route.build {
|
|
via = "$(output ${services.dhcpv4} router)";
|
|
target = "default";
|
|
dependencies = [ config.services.dhcpv4 ];
|
|
};
|
|
};
|
|
|
|
defaultProfile.packages = [ mtdutils ];
|
|
# Only keep root, which should inherit from DGN access control's root permissions.
|
|
users.root = config.users.root;
|
|
};
|
|
})
|
|
];
|
|
}
|