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"
This commit is contained in:
Daniel Barlow 2024-02-27 22:39:07 +00:00
parent 94dbc56595
commit 9d6e50cbbc
2 changed files with 112 additions and 64 deletions

View file

@ -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];
}

100
modules/profiles/wap.nix Normal file
View file

@ -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";
};
};
};
}