From 9d6e50cbbcd565a0a8c61c527ec1dcdc5048620c Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Tue, 27 Feb 2024 22:39:07 +0000 Subject: [PATCH] extract extneder example to a "profile" this is a bit of an experiment to reduce the copy-paste in examples by turning them into "application" modules. planning to follow up with another module for "wifi router" --- examples/extneder.nix | 76 +++++------------------------ modules/profiles/wap.nix | 100 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 64 deletions(-) create mode 100644 modules/profiles/wap.nix diff --git a/examples/extneder.nix b/examples/extneder.nix index 1b2fab5..69f5345 100644 --- a/examples/extneder.nix +++ b/examples/extneder.nix @@ -11,10 +11,6 @@ ... }: let secrets = import ./extneder-secrets.nix; - inherit (pkgs.liminix.services) oneshot longrun bundle target; - inherit (pkgs.pseudofile) dir symlink; - inherit (pkgs) dropbear ifwait serviceFns; - svc = config.system.service; in rec { boot = { tftp = { @@ -24,12 +20,8 @@ in rec { }; imports = [ - ../modules/wlan.nix + ../modules/profiles/wap.nix ../modules/vlan - ../modules/network - ../modules/hostapd - ../modules/bridge - ../modules/ssh ]; hostname = "extneder"; @@ -69,68 +61,24 @@ in rec { }; }; - services.hostap = svc.hostapd.build { - interface = config.hardware.networkInterfaces.wlan; - params = { - country_code = "GB"; - hw_mode = "g"; - wmm_enabled = 1; - ieee80211n = 1; - inherit (secrets) ssid channel wpa_passphrase; - auth_algs = 1; # 1=wpa2, 2=wep, 3=both - wpa = 2; # 1=wpa, 2=wpa2, 3=both - wpa_key_mgmt = "WPA-PSK"; - wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?) - rsn_pairwise = "CCMP"; # auth for wpa2 - }; - }; - - services.int = svc.bridge.primary.build { - ifname = "int"; - }; - - services.dhcpc = svc.network.dhcp.client.build { - interface = services.int; - dependencies = [ config.services.hostname ]; - }; - - services.bridge = svc.bridge.members.build { - primary = services.int; - members = with config.hardware.networkInterfaces; [ + profile.wap = { + interfaces = with config.hardware.networkInterfaces; [ lan wlan ]; - }; - services.sshd = svc.ssh.build {}; - - services.resolvconf = oneshot rec { - dependencies = [ services.dhcpc ]; - name = "resolvconf"; - # CHECK: https://udhcp.busybox.net/README.udhcpc says - # 'A list of DNS server' but doesn't say what separates the - # list members. Assuming it's a space or other IFS character - up = '' - . ${serviceFns} - ( in_outputs ${name} - for i in $(output ${services.dhcpc} dns); do - echo "nameserver $i" > resolv.conf - done - ) - ''; - }; - filesystem = dir { - etc = dir { - "resolv.conf" = symlink "${services.resolvconf}/.outputs/resolv.conf"; + wireless = { + networks.${secrets.ssid} = { + interface = config.hardware.networkInterfaces.wlan; + inherit (secrets) channel wpa_passphrase; + country_code = "GB"; + hw_mode = "g"; + wmm_enabled = 1; + ieee80211n = 1; + }; }; }; - services.defaultroute4 = svc.network.route.build { - via = "$(output ${services.dhcpc} router)"; - target = "default"; - dependencies = [services.dhcpc]; - }; - users.root.passwd = lib.mkForce secrets.root.passwd; defaultProfile.packages = with pkgs; [nftables strace tcpdump swconfig]; } diff --git a/modules/profiles/wap.nix b/modules/profiles/wap.nix new file mode 100644 index 0000000..5c95e99 --- /dev/null +++ b/modules/profiles/wap.nix @@ -0,0 +1,100 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (pkgs) liminix; + inherit (lib) mkEnableOption mkOption types isDerivation hasAttr ; + + inherit (pkgs.liminix.services) oneshot longrun bundle target; + inherit (pkgs.pseudofile) dir symlink; + inherit (pkgs) serviceFns; + svc = config.system.service; + cfg = config.profile.wap; + + hostaps = + let + defaults = { + auth_algs = 1; # 1=wpa2, 2=wep, 3=both + wpa = 2; # 1=wpa, 2=wpa2, 3=both + wpa_key_mgmt = "WPA-PSK"; + wpa_pairwise = "TKIP CCMP"; # auth for wpa (may not need this?) + rsn_pairwise = "CCMP"; # auth for wpa2 + }; + in lib.mapAttrs' + (name : value : + let + attrs = defaults // { ssid = name; } // value; + in lib.nameValuePair + "hostap-${name}" + (svc.hostapd.build { + interface = attrs.interface; + params = lib.filterAttrs (k: v: k != "interface") attrs; + })) + cfg.wireless.networks; + +in { + imports = [ + ../wlan.nix + ../network + ../hostapd + ../bridge + ../ssh + { config.services = hostaps; } + ]; + + options.profile.wap = { + interfaces = mkOption { + type = types.listOf liminix.lib.types.interface; + default = []; + }; + wireless = mkOption { + type = types.attrsOf types.anything; + }; + }; + config = { + services.sshd = svc.ssh.build {}; + + services.int = svc.bridge.primary.build { + ifname = "int"; + }; + + services.bridge = svc.bridge.members.build { + primary = config.services.int; + members = cfg.interfaces; + }; + + services.dhcpc = svc.network.dhcp.client.build { + interface = config.services.int; + dependencies = [ config.services.hostname ]; + }; + + services.defaultroute4 = svc.network.route.build { + via = "$(output ${config.services.dhcpc} router)"; + target = "default"; + dependencies = [config.services.dhcpc]; + }; + + services.resolvconf = oneshot rec { + dependencies = [ config.services.dhcpc ]; + name = "resolvconf"; + # CHECK: https://udhcp.busybox.net/README.udhcpc says + # 'A list of DNS server' but doesn't say what separates the + # list members. Assuming it's a space or other IFS character + up = '' + . ${serviceFns} + ( in_outputs ${name} + for i in $(output ${config.services.dhcpc} dns); do + echo "nameserver $i" > resolv.conf + done + ) + ''; + }; + filesystem = dir { + etc = dir { + "resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf"; + }; + }; + }; +}