From fde8f66ea77aee78b29bd4240d091f65ae4ce183 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Wed, 6 Mar 2024 19:14:58 +0100 Subject: [PATCH 01/28] feat: init Liminix evaluation system Very rudimentary; undocumented, untested in production. This is for testing purposes. Signed-off-by: Ryan Lahfa --- liminix-hive.nix | 38 +++++++++ machines/ap/configuration.nix | 140 ++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 liminix-hive.nix create mode 100644 machines/ap/configuration.nix diff --git a/liminix-hive.nix b/liminix-hive.nix new file mode 100644 index 00000000..563a9ce7 --- /dev/null +++ b/liminix-hive.nix @@ -0,0 +1,38 @@ +# This is a very rudimentary hive to deploy Liminix images. +{ + sources ? import ./npins, + nixpkgs ? sources.nixpkgs, + liminix ? sources.liminix, +}: +let + evalLiminix = + { + config, + device, + output, + }: + { + primary = + (import liminix { + inherit device nixpkgs; + imageType = "primary"; + liminix-config = config; + }).outputs.${output}; + secondary = + (import liminix { + inherit device nixpkgs; + imageType = "secondary"; + liminix-config = config; + }).outputs.${output}; + }; + zyxel = { + nwa50ax = import "${liminix}/devices/zyxel-nwa50ax"; + }; +in +{ + ap-test = evalLiminix { + config = ./machines/ap/configuration.nix; + device = zyxel.nwa50ax; + output = "zyxel-nwa-fit"; + }; +} diff --git a/machines/ap/configuration.nix b/machines/ap/configuration.nix new file mode 100644 index 00000000..a98a93cc --- /dev/null +++ b/machines/ap/configuration.nix @@ -0,0 +1,140 @@ +{ + config, + pkgs, + modulesPath, + ... +}: +let + # inherit (pkgs.liminix.services) + # oneshot + # longrun + # bundle + # target + # ; + # inherit (pkgs) writeText; + svc = config.system.service; + secrets-1 = { + ssid = "Zyxel 2G (N)"; + wpa_passphrase = "diamond dogs"; + }; + secrets-2 = { + ssid = "Zyxel 5G (AX)"; + wpa_passphrase = "diamond dogs"; + }; + 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_key_mgmt = "WPA-PSK"; + wpa_pairwise = "TKIP CCMP"; + rsn_pairwise = "CCMP"; + }; + + 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; + }; + mkWifiSta = + params: interface: secrets: + svc.hostapd.build { + inherit interface; + params = params // { + inherit (secrets) ssid wpa_passphrase; + }; + }; +in +rec { + imports = [ + "${modulesPath}/wlan.nix" + "${modulesPath}/network" + "${modulesPath}/hostapd" + "${modulesPath}/ssh" + "${modulesPath}/ntp" + "${modulesPath}/vlan" + "${modulesPath}/bridge" + ]; + + hostname = "zyxel"; + + users.root = { + # EDIT: choose a root password and then use + # "mkpasswd -m sha512crypt" to determine the hash. + # It should start wirh $6$. + passwd = "$y$j9T$f8GhLiqYmr3lc58eKhgyD0$z7P/7S9u.kq/cANZExxhS98bze/6i7aBxU6tbl7RMi."; + openssh.authorizedKeys.keys = [ + # EDIT: you can add your ssh pubkey here + # "ssh-rsa AAAAB3NzaC1....H6hKd user@example.com"; + ]; + }; + + services.int = svc.bridge.primary.build { ifname = "int"; }; + + services.bridge = svc.bridge.members.build { + primary = services.int; + members = with config.hardware.networkInterfaces; [ + lan + wlan0 + wlan1 + ]; + }; + + services.dhcpv4 = + let + iface = services.int; + in + svc.network.dhcp.client.build { interface = iface; }; + + services.defaultroute4 = svc.network.route.build { + via = "$(output ${services.dhcpv4} address)"; + 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" ]; + }; + }; + + boot.tftp = { + serverip = "192.0.2.10"; + ipaddr = "192.0.2.12"; + }; + + # wlan0 is the 2.4GHz interface. + services.hostap-1 = mkWifiSta baseParams config.hardware.networkInterfaces.wlan0 secrets-1; + # wlan1 is the 5GHz interface, e.g. AX capable. + services.hostap-2 = + mkWifiSta (baseParams // modernParams) config.hardware.networkInterfaces.wlan1 + secrets-2; + + defaultProfile.packages = with pkgs; [ + zyxel-bootconfig + iw + min-collect-garbage + mtdutils + ]; +} From 17b2345a02ad47ab15b6626d8f3bc95236b25b35 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Wed, 6 Mar 2024 21:28:27 +0100 Subject: [PATCH 02/28] feat: add liminix-rebuild in the shell Signed-off-by: Ryan Lahfa --- default.nix | 2 ++ liminix-hive.nix | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/default.nix b/default.nix index d04dfadb..e4c0d084 100644 --- a/default.nix +++ b/default.nix @@ -37,6 +37,7 @@ let sources = import ./npins; pkgs = import sources.nixpkgs { }; + liminixHive = import ./liminix-hive.nix { inherit sources; }; pre-commit-check = (import sources.pre-commit-hooks).run { src = ./.; @@ -77,6 +78,7 @@ in npins nixos-generators attic-client + liminixHive.liminix.pkgs.pkgsBuildBuild.min-copy-closure ] ++ (builtins.map (p: callPackage p { }) [ (sources.disko + "/package.nix") diff --git a/liminix-hive.nix b/liminix-hive.nix index 563a9ce7..94c65dea 100644 --- a/liminix-hive.nix +++ b/liminix-hive.nix @@ -30,6 +30,13 @@ let }; in { + liminix.pkgs = + (import liminix { + device = zyxel.nwa50ax; + imageType = "primary"; + liminix-config = ./machines/ap/configuration.nix; + }).pkgs; + devices = zyxel; ap-test = evalLiminix { config = ./machines/ap/configuration.nix; device = zyxel.nwa50ax; From aa6b082b819e673fbb1f47602d16887e4439ef89 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Wed, 6 Mar 2024 21:50:45 +0100 Subject: [PATCH 03/28] feat: enable liminix-rebuild Signed-off-by: Ryan Lahfa --- liminix-hive.nix | 29 +++++++++++------------------ liminix-rebuild.nix | 1 + 2 files changed, 12 insertions(+), 18 deletions(-) create mode 100644 liminix-rebuild.nix diff --git a/liminix-hive.nix b/liminix-hive.nix index 94c65dea..a9be921b 100644 --- a/liminix-hive.nix +++ b/liminix-hive.nix @@ -6,24 +6,18 @@ }: let evalLiminix = + { config, device }: { - config, - device, - output, - }: - { - primary = - (import liminix { - inherit device nixpkgs; - imageType = "primary"; - liminix-config = config; - }).outputs.${output}; - secondary = - (import liminix { - inherit device nixpkgs; - imageType = "secondary"; - liminix-config = config; - }).outputs.${output}; + primary = import liminix { + inherit device nixpkgs; + imageType = "primary"; + liminix-config = config; + }; + secondary = import liminix { + inherit device nixpkgs; + imageType = "secondary"; + liminix-config = config; + }; }; zyxel = { nwa50ax = import "${liminix}/devices/zyxel-nwa50ax"; @@ -40,6 +34,5 @@ in ap-test = evalLiminix { config = ./machines/ap/configuration.nix; device = zyxel.nwa50ax; - output = "zyxel-nwa-fit"; }; } diff --git a/liminix-rebuild.nix b/liminix-rebuild.nix new file mode 100644 index 00000000..1bca642a --- /dev/null +++ b/liminix-rebuild.nix @@ -0,0 +1 @@ +{ liminix-system }: (import ./liminix-hive.nix { }).${liminix-system}.primary From 41ca207b4108ae029131720184c249023ce18f2e Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 12 May 2024 23:25:26 +0200 Subject: [PATCH 04/28] feat: wip! wip! wip! --- hive.nix | 50 +++++++++++++++++++++++++++++++++++++++++++--- npins/sources.json | 8 ++++---- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/hive.nix b/hive.nix index 1f539193..85968cd6 100644 --- a/hive.nix +++ b/hive.nix @@ -52,11 +52,35 @@ let nodeMeta = meta.nodes.${node}; }; + + apDevice = import "${sources.liminix}/devices/zyxel-nwa50ax"; + apOverlay = import "${sources.liminix}/overlay.nix"; + + apNixpkgs = import (mkNixpkgs' "unstable") ( + apDevice.system + // { + overlays = [ apOverlay ]; + config = { + allowUnsupportedSystem = true; # mipsel + permittedInsecurePackages = [ + "python-2.7.18.8" # Python < 3 is needed for kernel backports. + ]; + }; + } + ); in { + registry = { + liminix = { + evalConfig = import "${sources.liminix}/lib/eval-config.nix" { inherit (sources) nixpkgs; }; + }; + }; + meta = { - nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${version n}) nodes; + nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${version n}) nodes // { + ap01 = apNixpkgs; + }; specialArgs = { inherit nixpkgs sources; @@ -65,8 +89,8 @@ in nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes; }; - defaults = - { name, nodeMeta, ... }: + registry.nixos.defaults = + { nodeMeta, name, ... }: { # Import the default modules imports = [ ./modules ]; @@ -97,5 +121,25 @@ in inherit (nodeMeta) stateVersion; }; }; + + ap01 = + let + device = import "${sources.liminix}/devices/zyxel-nwa50ax"; + in + { + deployment.systemType = "liminix"; + nixpkgs.hostPlatform = { + config = "mipsel-unknown-linux-musl"; + gcc = { + abi = "32"; + arch = "mips32"; # mips32r2? + }; + }; + nixpkgs.buildPlatform = "x86_64-linux"; + imports = [ + ./machines/ap/configuration.nix + device.module + ]; + }; } // (lib.mapSingleFuse mkNode nodes) diff --git a/npins/sources.json b/npins/sources.json index 3db11630..ae566c94 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -72,10 +72,10 @@ "owner": "RaitoBezarius", "repo": "liminix" }, - "branch": "nwa50ax", - "revision": "a4aa10dcc30225a8bb8eb465abfe908629175f2c", - "url": "https://github.com/RaitoBezarius/liminix/archive/a4aa10dcc30225a8bb8eb465abfe908629175f2c.tar.gz", - "hash": "1m1sc6agg5z65lmyjl48i7sddlwm8d0zgvs8z81iammfy4jpy7qd" + "branch": "colmena--compat", + "revision": "411a6bc688763fe62d210ccfe066a6cea72a9dce", + "url": "https://github.com/RaitoBezarius/liminix/archive/411a6bc688763fe62d210ccfe066a6cea72a9dce.tar.gz", + "hash": "17wg5288z3085rd4day1qqi1pm0cmibmcm6nrqrgrc1w1iwja9f0" }, "linkal": { "type": "Git", From 0a948e6148f9add3dfefb288752c9daf870648e9 Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Mon, 13 May 2024 17:04:49 +0200 Subject: [PATCH 05/28] feat: Specialize nixpkgs as a function of the system --- hive.nix | 77 ++++++++++++++++++++--------------- machines/ap/configuration.nix | 6 +-- meta/nixpkgs.nix | 27 ++++++++---- meta/nodes.nix | 7 ++++ meta/options.nix | 14 ++++++- 5 files changed, 86 insertions(+), 45 deletions(-) diff --git a/hive.nix b/hive.nix index 85968cd6..70f10d18 100644 --- a/hive.nix +++ b/hive.nix @@ -17,12 +17,16 @@ let }; nixpkgs' = import ./meta/nixpkgs.nix; + # All supported nixpkgs versions, instanciated - nixpkgs = lib.mapSingleFuse mkNixpkgs nixpkgs'.supported; + nixpkgs = lib.mapSingleFuse ( + s: lib.mapSingleFuse (mkSystemNixpkgs s) nixpkgs'.versions.supported + ) nixpkgs'.systems.supported; # Get the configured nixos version for the node, # defaulting to the one defined in meta/nixpkgs - version = node: nodes'.${node}.nixpkgs or nixpkgs'.default; + version = node: nodes'.${node}.nixpkgs or nixpkgs'.versions.default; + system = node: nodes'.${node}.system or nixpkgs'.systems.default; # Builds a patched version of nixpkgs, only as the source mkNixpkgs' = @@ -35,55 +39,62 @@ let inherit version; }; - # Instanciates the required nixpkgs version - mkNixpkgs = version: import (mkNixpkgs' version) { }; + # Instanciate a specialized version of nixpkgs + mkSystemNixpkgs = + system: version: + let + args = + if system == "nixos" then + { } + else + (import "${sources.liminix}/devices/${system}").system + // { + overlays = [ (import "${sources.liminix}/overlay.nix") ]; + config = { + allowUnsupportedSystem = true; # mipsel + permittedInsecurePackages = [ + "python-2.7.18.8" # Python < 3 is needed for kernel backports. + ]; + }; + }; + in + import (mkNixpkgs' version) args; ### # Function to create arguments based on the node # - mkArgs = node: rec { - lib = import sources.nix-lib { - inherit (nixpkgs.${version node}) lib; + mkArgs = + node: + let + pkgs = nixpkgs.${system node}; + in + rec { + lib = import sources.nix-lib { + inherit (pkgs.${version node}) lib; - keysRoot = ./keys; - }; + nixpkgs = pkgs; - meta = (import ./meta) lib; - - nodeMeta = meta.nodes.${node}; - }; - - apDevice = import "${sources.liminix}/devices/zyxel-nwa50ax"; - apOverlay = import "${sources.liminix}/overlay.nix"; - - apNixpkgs = import (mkNixpkgs' "unstable") ( - apDevice.system - // { - overlays = [ apOverlay ]; - config = { - allowUnsupportedSystem = true; # mipsel - permittedInsecurePackages = [ - "python-2.7.18.8" # Python < 3 is needed for kernel backports. - ]; + keysRoot = ./keys; }; - } - ); + + meta = (import ./meta) lib; + + nodeMeta = meta.nodes.${node}; + }; in { registry = { liminix = { - evalConfig = import "${sources.liminix}/lib/eval-config.nix" { inherit (sources) nixpkgs; }; + evalConfig = import "${sources.liminix}/lib/eval-config.nix" { nixpkgs = sources.nixos-unstable; }; }; }; meta = { - nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${version n}) nodes // { - ap01 = apNixpkgs; - }; + nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${system n}.${version n}) nodes; specialArgs = { - inherit nixpkgs sources; + inherit sources; }; nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes; diff --git a/machines/ap/configuration.nix b/machines/ap/configuration.nix index a98a93cc..716256d9 100644 --- a/machines/ap/configuration.nix +++ b/machines/ap/configuration.nix @@ -127,9 +127,9 @@ rec { # wlan0 is the 2.4GHz interface. services.hostap-1 = mkWifiSta baseParams config.hardware.networkInterfaces.wlan0 secrets-1; # wlan1 is the 5GHz interface, e.g. AX capable. - services.hostap-2 = - mkWifiSta (baseParams // modernParams) config.hardware.networkInterfaces.wlan1 - secrets-2; + services.hostap-2 = mkWifiSta ( + baseParams // modernParams + ) config.hardware.networkInterfaces.wlan1 secrets-2; defaultProfile.packages = with pkgs; [ zyxel-bootconfig diff --git a/meta/nixpkgs.nix b/meta/nixpkgs.nix index b8c6b433..106f46ca 100644 --- a/meta/nixpkgs.nix +++ b/meta/nixpkgs.nix @@ -1,10 +1,23 @@ { - # Default version of nixpkgs to use - default = "23.11"; + versions = { + # Default version of nixpkgs to use + default = "23.11"; - # Supported nixpkgs versions - supported = [ - "unstable" - "23.11" - ]; + # Supported nixpkgs versions + supported = [ + "unstable" + "23.11" + ]; + }; + + systems = { + # Default target system + default = "nixos"; + + # Supported target systems + supported = [ + "nixos" + "zyxel-nwa50ax" + ]; + }; } diff --git a/meta/nodes.nix b/meta/nodes.nix index ba634f64..2773af34 100644 --- a/meta/nodes.nix +++ b/meta/nodes.nix @@ -86,4 +86,11 @@ stateVersion = "23.11"; vm-cluster = "Hyperviseur Luj"; }; + + # Access points definition + ap01 = { + site = "unknown"; + + system = "zyxel-nwa50ax"; + }; } diff --git a/meta/options.nix b/meta/options.nix index 7bae727c..0cc6e9fd 100644 --- a/meta/options.nix +++ b/meta/options.nix @@ -11,6 +11,7 @@ let inherit (lib.types) attrs attrsOf + enum ints listOf nullOr @@ -35,6 +36,7 @@ let }; org = config.organization; + nixpkgs = import ./nixpkgs.nix; in { @@ -124,8 +126,8 @@ in }; nixpkgs = mkOption { - type = str; - inherit (import ./nixpkgs.nix) default; + type = enum nixpkgs.versions.supported; + inherit (nixpkgs.versions) default; description = '' Version of nixpkgs to use. ''; @@ -167,6 +169,14 @@ in default = null; description = "VM cluster where the VM is located"; }; + + system = mkOption { + type = enum nixpkgs.systems.supported; + inherit (nixpkgs.systems) default; + description = '' + Type of system for the node, will impact how it is evaluated and deployed. + ''; + }; }; config = { From 5a8fe24dce32af842a1b18d77070152b286e4923 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Fri, 24 May 2024 18:34:32 +0200 Subject: [PATCH 06/28] feat: achieve custom evaluation in the framework Signed-off-by: Ryan Lahfa --- default.nix | 22 ++-- hive.nix | 111 +++++++++--------- liminix-hive.nix | 38 ------ .../_configuration.nix} | 0 machines/ap01/_hardware-configuration.nix | 1 + npins/default.nix | 1 + npins/sources.json | 24 ++-- 7 files changed, 83 insertions(+), 114 deletions(-) delete mode 100644 liminix-hive.nix rename machines/{ap/configuration.nix => ap01/_configuration.nix} (100%) create mode 100644 machines/ap01/_hardware-configuration.nix diff --git a/default.nix b/default.nix index e4c0d084..0616e5b5 100644 --- a/default.nix +++ b/default.nix @@ -37,8 +37,6 @@ let sources = import ./npins; pkgs = import sources.nixpkgs { }; - liminixHive = import ./liminix-hive.nix { inherit sources; }; - pre-commit-check = (import sources.pre-commit-hooks).run { src = ./.; @@ -72,19 +70,13 @@ in name = "dgnum-infra"; packages = - ( - with pkgs; - [ - npins - nixos-generators - attic-client - liminixHive.liminix.pkgs.pkgsBuildBuild.min-copy-closure - ] - ++ (builtins.map (p: callPackage p { }) [ - (sources.disko + "/package.nix") - ./lib/colmena - ]) - ) + (with pkgs; [ + npins + nixos-generators + attic-client + (callPackage (sources.disko + "/package.nix") { }) + (callPackage ./lib/colmena { colmena = import sources.colmena; }) + ]) ++ (import ./scripts { inherit pkgs; }); shellHook = '' diff --git a/hive.nix b/hive.nix index 70f10d18..51835bb1 100644 --- a/hive.nix +++ b/hive.nix @@ -2,6 +2,7 @@ let sources = import ./npins; lib = import (sources.nix-lib + "/src/trivial.nix"); + lib' = (import sources.nixos-unstable { }).lib; patch = import sources.nix-patches { patchFile = ./patches; }; @@ -14,6 +15,8 @@ let "_configuration.nix" "_hardware-configuration.nix" ]; + + deployment.systemType = systemType node; }; nixpkgs' = import ./meta/nixpkgs.nix; @@ -27,6 +30,10 @@ let # defaulting to the one defined in meta/nixpkgs version = node: nodes'.${node}.nixpkgs or nixpkgs'.versions.default; system = node: nodes'.${node}.system or nixpkgs'.systems.default; + systemType = + node: + nodes'.${node}.system + or (lib'.warn "Not specifying the `deployment.systemType` is deprecated!" "nixos"); # Builds a patched version of nixpkgs, only as the source mkNixpkgs' = @@ -85,8 +92,57 @@ in { registry = { - liminix = { + zyxel-nwa50ax = { evalConfig = import "${sources.liminix}/lib/eval-config.nix" { nixpkgs = sources.nixos-unstable; }; + + defaults = { + nixpkgs.hostPlatform = { + config = "mipsel-unknown-linux-musl"; + gcc = { + abi = "32"; + arch = "mips32"; # mips32r2? + }; + }; + # It's impure, but who cares? + # Can Flakes do that? + nixpkgs.buildPlatform = builtins.currentSystem; + }; + }; + + nixos = { + evalConfig = import "${sources.nixos-unstable}/nixos/lib/eval-config.nix"; + defaults = + { nodeMeta, name, ... }: + { + # Import the default modules + imports = [ ./modules ]; + + # Include default secrets + age-secrets.sources = [ ./machines/${name}/secrets ]; + + # Deployment config is specified in meta.nodes.${node}.deployment + inherit (nodeMeta) deployment; + + nix = { + # Set NIX_PATH to the patched version of nixpkgs + nixPath = [ "nixpkgs=${mkNixpkgs' (version name)}" ]; + optimise.automatic = true; + + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 7d"; + }; + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # Use the stateVersion declared in the metadata + system = { + inherit (nodeMeta) stateVersion; + }; + }; }; }; @@ -99,58 +155,5 @@ in nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes; }; - - registry.nixos.defaults = - { nodeMeta, name, ... }: - { - # Import the default modules - imports = [ ./modules ]; - - # Include default secrets - age-secrets.sources = [ ./machines/${name}/secrets ]; - - # Deployment config is specified in meta.nodes.${node}.deployment - inherit (nodeMeta) deployment; - - nix = { - # Set NIX_PATH to the patched version of nixpkgs - nixPath = [ "nixpkgs=${mkNixpkgs' (version name)}" ]; - optimise.automatic = true; - - gc = { - automatic = true; - dates = "weekly"; - options = "--delete-older-than 7d"; - }; - }; - - # Allow unfree packages - nixpkgs.config.allowUnfree = true; - - # Use the stateVersion declared in the metadata - system = { - inherit (nodeMeta) stateVersion; - }; - }; - - ap01 = - let - device = import "${sources.liminix}/devices/zyxel-nwa50ax"; - in - { - deployment.systemType = "liminix"; - nixpkgs.hostPlatform = { - config = "mipsel-unknown-linux-musl"; - gcc = { - abi = "32"; - arch = "mips32"; # mips32r2? - }; - }; - nixpkgs.buildPlatform = "x86_64-linux"; - imports = [ - ./machines/ap/configuration.nix - device.module - ]; - }; } // (lib.mapSingleFuse mkNode nodes) diff --git a/liminix-hive.nix b/liminix-hive.nix deleted file mode 100644 index a9be921b..00000000 --- a/liminix-hive.nix +++ /dev/null @@ -1,38 +0,0 @@ -# This is a very rudimentary hive to deploy Liminix images. -{ - sources ? import ./npins, - nixpkgs ? sources.nixpkgs, - liminix ? sources.liminix, -}: -let - evalLiminix = - { config, device }: - { - primary = import liminix { - inherit device nixpkgs; - imageType = "primary"; - liminix-config = config; - }; - secondary = import liminix { - inherit device nixpkgs; - imageType = "secondary"; - liminix-config = config; - }; - }; - zyxel = { - nwa50ax = import "${liminix}/devices/zyxel-nwa50ax"; - }; -in -{ - liminix.pkgs = - (import liminix { - device = zyxel.nwa50ax; - imageType = "primary"; - liminix-config = ./machines/ap/configuration.nix; - }).pkgs; - devices = zyxel; - ap-test = evalLiminix { - config = ./machines/ap/configuration.nix; - device = zyxel.nwa50ax; - }; -} diff --git a/machines/ap/configuration.nix b/machines/ap01/_configuration.nix similarity index 100% rename from machines/ap/configuration.nix rename to machines/ap01/_configuration.nix diff --git a/machines/ap01/_hardware-configuration.nix b/machines/ap01/_hardware-configuration.nix new file mode 100644 index 00000000..ffcd4415 --- /dev/null +++ b/machines/ap01/_hardware-configuration.nix @@ -0,0 +1 @@ +{ } diff --git a/npins/default.nix b/npins/default.nix index 43cead31..14589ce3 100644 --- a/npins/default.nix +++ b/npins/default.nix @@ -42,6 +42,7 @@ let builtins.fetchGit { inherit (repository) url; rev = revision; + allRefs = true; # hash = hash; }; diff --git a/npins/sources.json b/npins/sources.json index ae566c94..32d2ca35 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -38,6 +38,17 @@ "url": "https://github.com/zhaofengli/attic/archive/4dbdbee45728d8ce5788db6461aaaa89d98081f0.tar.gz", "hash": "1iri77pbf0gvas93zra29qy1c3l61n97z84xblqxmmhsxvljzvnh" }, + "colmena": { + "type": "Git", + "repository": { + "type": "Git", + "url": "https://git.dgnum.eu/DGNum/colmena.git" + }, + "branch": "custom-activation", + "revision": "937ca4d17aecd3ae7394a2a1772dd3e705cb5779", + "url": null, + "hash": "11n9qdm0zi3s89zdcdmyv4l4wv5aq8b4sigx54cp24plxszxrsa7" + }, "disko": { "type": "GitRelease", "repository": { @@ -68,14 +79,13 @@ "liminix": { "type": "Git", "repository": { - "type": "GitHub", - "owner": "RaitoBezarius", - "repo": "liminix" + "type": "Git", + "url": "https://git.dgnum.eu/DGNum/liminix.git" }, - "branch": "colmena--compat", - "revision": "411a6bc688763fe62d210ccfe066a6cea72a9dce", - "url": "https://github.com/RaitoBezarius/liminix/archive/411a6bc688763fe62d210ccfe066a6cea72a9dce.tar.gz", - "hash": "17wg5288z3085rd4day1qqi1pm0cmibmcm6nrqrgrc1w1iwja9f0" + "branch": "main", + "revision": "7ae86c23d96b5e6a59fff4d8ebcb3e2e90e4034f", + "url": null, + "hash": "1kw6jp5xnpwnpl2pal3qpr5ljrsvjish4v4m0brnxchc8s1ygq6i" }, "linkal": { "type": "Git", From 3ed6ecba317d5c5487046ea8698b499744476535 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Fri, 14 Jun 2024 22:19:32 +0200 Subject: [PATCH 07/28] feat: ensure that `colmena repl` can evaluate `nodes.ap01` Bump to latest Liminix and use the new `defaults` function. Signed-off-by: Ryan Lahfa --- hive.nix | 2 +- npins/sources.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hive.nix b/hive.nix index 51835bb1..71180d5e 100644 --- a/hive.nix +++ b/hive.nix @@ -95,7 +95,7 @@ in zyxel-nwa50ax = { evalConfig = import "${sources.liminix}/lib/eval-config.nix" { nixpkgs = sources.nixos-unstable; }; - defaults = { + defaults = _: { nixpkgs.hostPlatform = { config = "mipsel-unknown-linux-musl"; gcc = { diff --git a/npins/sources.json b/npins/sources.json index 32d2ca35..84f9911b 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -45,9 +45,9 @@ "url": "https://git.dgnum.eu/DGNum/colmena.git" }, "branch": "custom-activation", - "revision": "937ca4d17aecd3ae7394a2a1772dd3e705cb5779", + "revision": "1037471d800d3db42ec85b89787bec5472f5e574", "url": null, - "hash": "11n9qdm0zi3s89zdcdmyv4l4wv5aq8b4sigx54cp24plxszxrsa7" + "hash": "0k287292yr78zymdglppa8jd0b4kh0x277d4bycwcdsqprw00a4x" }, "disko": { "type": "GitRelease", @@ -83,9 +83,9 @@ "url": "https://git.dgnum.eu/DGNum/liminix.git" }, "branch": "main", - "revision": "7ae86c23d96b5e6a59fff4d8ebcb3e2e90e4034f", + "revision": "7206fea4b4e9a5e50be91cce39c09da602cdb694", "url": null, - "hash": "1kw6jp5xnpwnpl2pal3qpr5ljrsvjish4v4m0brnxchc8s1ygq6i" + "hash": "0dd7r80skjamx1sppsl6mdmjhr355lbmc72g0l0356xs67mg8w5p" }, "linkal": { "type": "Git", From 8b66b2b7c3f8f2c68c6b10c5974608e680708148 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Thu, 22 Aug 2024 18:45:40 +0200 Subject: [PATCH 08/28] feat: add access control for APs via our custom modules It works! Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 17 +++++++++-------- meta/nodes.nix | 1 + meta/organization.nix | 6 ++++++ modules/dgn-access-control.nix | 25 +++++++++++++++++-------- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index 716256d9..0284ae01 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -14,11 +14,11 @@ let # inherit (pkgs) writeText; svc = config.system.service; secrets-1 = { - ssid = "Zyxel 2G (N)"; + ssid = "DGNum 2G prototype (N)"; wpa_passphrase = "diamond dogs"; }; secrets-2 = { - ssid = "Zyxel 5G (AX)"; + ssid = "DGNum 5G prototype (AX)"; wpa_passphrase = "diamond dogs"; }; baseParams = { @@ -72,19 +72,20 @@ rec { "${modulesPath}/ntp" "${modulesPath}/vlan" "${modulesPath}/bridge" + ../../modules/dgn-access-control.nix + # TODO: god that's so a fucking hack. + (import "${modulesPath}/../devices/zyxel-nwa50ax").module ]; - hostname = "zyxel"; + hostname = "ap01-prototype"; + # SSH keys are handled by the access control module. + dgn-access-control.enable = true; users.root = { # EDIT: choose a root password and then use # "mkpasswd -m sha512crypt" to determine the hash. # It should start wirh $6$. - passwd = "$y$j9T$f8GhLiqYmr3lc58eKhgyD0$z7P/7S9u.kq/cANZExxhS98bze/6i7aBxU6tbl7RMi."; - openssh.authorizedKeys.keys = [ - # EDIT: you can add your ssh pubkey here - # "ssh-rsa AAAAB3NzaC1....H6hKd user@example.com"; - ]; + passwd = "$6$jVXFFOp8HBYmgINR$lutB4kvw.W1jlXRby9ZYAgBitQ32RxQdYAGN.s2x4ris8J07vM6tzlRBQoeLELOIEMClDzbciQV0itfHQnTqd1"; }; services.int = svc.bridge.primary.build { ifname = "int"; }; diff --git a/meta/nodes.nix b/meta/nodes.nix index 2773af34..d538a1b7 100644 --- a/meta/nodes.nix +++ b/meta/nodes.nix @@ -90,6 +90,7 @@ # Access points definition ap01 = { site = "unknown"; + adminGroups = [ "fai" ]; system = "zyxel-nwa50ax"; }; diff --git a/meta/organization.nix b/meta/organization.nix index cf5eab5b..b8248b83 100644 --- a/meta/organization.nix +++ b/meta/organization.nix @@ -87,6 +87,12 @@ "fai" ]; + # AP administration DGNum + ap.adminGroups = [ + "root" + "fai" + ]; + # Videos DGNum peertube.admins = [ "thubrecht" ]; }; diff --git a/modules/dgn-access-control.nix b/modules/dgn-access-control.nix index 375ea9c7..28bd7db0 100644 --- a/modules/dgn-access-control.nix +++ b/modules/dgn-access-control.nix @@ -44,6 +44,7 @@ let mkDefault mkEnableOption mkIf + mkMerge mkOption types @@ -78,12 +79,20 @@ in }; }; - config = mkIf cfg.enable { - # Admins have root access to the node - dgn-access-control.users.root = mkDefault admins; - - users.users = builtins.mapAttrs (_: members: { - openssh.authorizedKeys.keys = lib.extra.getAllKeys members; - }) cfg.users; - }; + config = mkIf cfg.enable (mkMerge [ + { + # Admins have root access to the node + dgn-access-control.users.root = mkDefault admins; + } + (mkIf (nodeMeta.system == "nixos") { + users.users = builtins.mapAttrs (_: members: { + openssh.authorizedKeys.keys = lib.extra.getAllKeys members; + }) cfg.users; + }) + (mkIf (nodeMeta.system == "zyxel-nwa50ax") { + users = builtins.mapAttrs (_: members: { + openssh.authorizedKeys.keys = lib.extra.getAllKeys members; + }) cfg.users; + }) + ]); } From be1673c6aad389f713e6c2a3bc40b77af8e81bcd Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sat, 31 Aug 2024 22:20:24 +0200 Subject: [PATCH 09/28] feat(devshell): add liminix-related tools serial console, deployment tools and TFTP tool Signed-off-by: Ryan Lahfa --- default.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/default.nix b/default.nix index 0616e5b5..7655a8b0 100644 --- a/default.nix +++ b/default.nix @@ -74,6 +74,17 @@ in npins nixos-generators attic-client + picocom + (callPackage (sources.liminix + "/pkgs/min-copy-closure") { + nix = pkgs.lix; + }) + (callPackage (sources.liminix + "/pkgs/min-collect-garbage") { + nix = pkgs.lix; + }) + (callPackage (sources.liminix + "/pkgs/tufted") + { + } + ) (callPackage (sources.disko + "/package.nix") { }) (callPackage ./lib/colmena { colmena = import sources.colmena; }) ]) From c4d9d6d000e31e11d2a5623d2fa30f6fa8c8905c Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sat, 31 Aug 2024 22:21:35 +0200 Subject: [PATCH 10/28] feat(ap01): enable fully RADIUS via internal RADIUS server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds two public keys. For the private keys, heh… Signed-off-by: Ryan Lahfa --- keys/certs/dgnum-ap-server.crt | 18 ++++++++ keys/certs/dgnum-test-ap-ca.crt | 23 ++++++++++ machines/ap01/_configuration.nix | 75 ++++++++++++++++++++++++++++---- npins/sources.json | 15 ++++--- 4 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 keys/certs/dgnum-ap-server.crt create mode 100644 keys/certs/dgnum-test-ap-ca.crt diff --git a/keys/certs/dgnum-ap-server.crt b/keys/certs/dgnum-ap-server.crt new file mode 100644 index 00000000..ede405ee --- /dev/null +++ b/keys/certs/dgnum-ap-server.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC6TCCAdECFEbjeqNNzKWyfs2GJekipWK+yO4uMA0GCSqGSIb3DQEBCwUAMHMx +NDAyBgNVBAMMK0RHTnVtIFRlc3QgQVAgQ0EgLS0gRE8gTk9UIFVTRSBPUiBHRVQg +RklSRUQxCzAJBgNVBAYTAkZSMQ4wDAYDVQQIDAVQYXJpczEOMAwGA1UEBwwFUGFy +aXMxDjAMBgNVBAoMBURHTnVtMB4XDTI0MDgyNjE5MDQxMFoXDTI2MDgyNjE5MDQx +MFowdzE4MDYGA1UEAwwvREdOdW0gVGVzdCBBUCBzZXJ2ZXIgLS0gRE8gTk9UIFVT +RSBPUiBHRVQgRklSRUQxCzAJBgNVBAYTAkZSMQ4wDAYDVQQIDAVQYXJpczEOMAwG +A1UEBwwFUGFyaXMxDjAMBgNVBAoMBURHTnVtMIGbMBAGByqGSM49AgEGBSuBBAAj +A4GGAAQBDrTf0SH/YOkOfvOSnB3BbICb80jSsxwQH50y4jylbXcrUZnegLYjW/lF +QknuMBzzE5fnE9lAeOxqsn0ec+sL3zEBrV0LSG2LgxhAkahZS9U4Spt9Qc84U7cG +AFQ3GXDMTEb/COHJSu7sIfV4gFRVesFez30gb94lMxckkq/6nkXXaEUwDQYJKoZI +hvcNAQELBQADggEBAEfPHMAXwftYQ0lDYPlr9b+GZDl7/JAavEfBXKzj1U8O0sJz +daNOHEX3a5ZOaQoean2zmBLROgQpDlwsjAFNA9dg0ef2f4RgJvr/l2fspHwG0Uaq +4JEOKTj3htd8aZX2i6AR02UC2oxCtf7ZVa+a6NOeeKl53QPzjduPO60ruz8tD2Xr +YnQwVinQX0fJo7TmyQKDIxwld/Q5pMoDMfVlS71M/vISFfQ/Rx1PqYvBQyG1dvIA +qn9cNNVnjEGrk7zXjCfehMYiCtDZ+D3VyXeZ6A7YZNpc6RUj8rbWcOtKLayRFlwf +DTjV3/nPqV0M2nU6jXFBMfQ47VSfB7ibINt94xo= +-----END CERTIFICATE----- diff --git a/keys/certs/dgnum-test-ap-ca.crt b/keys/certs/dgnum-test-ap-ca.crt new file mode 100644 index 00000000..48e9129a --- /dev/null +++ b/keys/certs/dgnum-test-ap-ca.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDxzCCAq+gAwIBAgIUPuHEZeZoCidp+w5ME2CrkZEn3T8wDQYJKoZIhvcNAQEL +BQAwczE0MDIGA1UEAwwrREdOdW0gVGVzdCBBUCBDQSAtLSBETyBOT1QgVVNFIE9S +IEdFVCBGSVJFRDELMAkGA1UEBhMCRlIxDjAMBgNVBAgMBVBhcmlzMQ4wDAYDVQQH +DAVQYXJpczEOMAwGA1UECgwFREdOdW0wHhcNMjQwODI2MTg1ODQ4WhcNMjkwODI2 +MTg1ODQ4WjBzMTQwMgYDVQQDDCtER051bSBUZXN0IEFQIENBIC0tIERPIE5PVCBV +U0UgT1IgR0VUIEZJUkVEMQswCQYDVQQGEwJGUjEOMAwGA1UECAwFUGFyaXMxDjAM +BgNVBAcMBVBhcmlzMQ4wDAYDVQQKDAVER051bTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKLgCNXLI6FQWJY5JQDqZcO1hmZpp0upT59/JvJXmEl4St1O +FF3frSAoFcgn2Bv3kYQQ6wEhD3S7JBxRmoDtx/7sqsXthNpBaymVdphb9XhnVOC2 +NDBKV4WH06Hr06oKVfDSBhIldPJr1vfQLehOnz6uqK7walqPvid3tMv0lwt7mHZ9 +qQpgC2C/tkHwD1kh1RszoIZKIQWDnSNXPhYnB3X/DMCUWIKiz6P/0rVANEDDZER6 +b6eJRjv2l8jPlOt7CUTAOrsoJGCnSg2SV4lgr1u3mE/2AvmLdO0l5Dz0qCuQNbb3 +uWqYUonooR8rox171On/Rd0zvtihycSDxofVJ+MCAwEAAaNTMFEwHQYDVR0OBBYE +FIPUT3v8AoeBS6VbcEvgVc1dC38hMB8GA1UdIwQYMBaAFIPUT3v8AoeBS6VbcEvg +Vc1dC38hMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACX1aqYU +9PIwZ/dBS7cpsBsCm9M0ueInTlQpvv6xioKuPhIet40YgawTRakxniAr0WXHTBV5 +a8ZQ4ff4uI+sdaxN7Ueufr4ltWVLuSc9DfIxjLVZ+41G6Ehy9Xc2zoDBfYURrXjd +ISvPSXIKjM0yuS/249C77HOdzwbliS65Io2zubQStGfSaZ3sLAfPJoig+QiVyOtG +sPoYzzrjXDBym+plfGTWqHv+gwo6DZarXrK4yaMn4hYkkf95NsY2ywwHzcy/4hsu ++bMm4IeCrB9uNOZtQrqW81/+4oxjGiKLbhnFPNQOg2pzb+iOJTPKVicAqKDSCnou +WXG5pjBKzojPvxU= +-----END CERTIFICATE----- diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index 0284ae01..c894045c 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -15,11 +15,9 @@ let svc = config.system.service; secrets-1 = { ssid = "DGNum 2G prototype (N)"; - wpa_passphrase = "diamond dogs"; }; secrets-2 = { ssid = "DGNum 5G prototype (AX)"; - wpa_passphrase = "diamond dogs"; }; baseParams = { country_code = "FR"; @@ -30,11 +28,14 @@ let ht_capab = "[LDPC][GF][HT40-][HT40+][SHORT-GI-40][MAX-AMSDU-7935][TX-STBC]"; auth_algs = 1; wpa = 2; - wpa_key_mgmt = "WPA-PSK"; wpa_pairwise = "TKIP CCMP"; rsn_pairwise = "CCMP"; }; + radiusKeyMgmt = { + wpa_key_mgmt = "WPA-EAP"; + }; + modernParams = { hw_mode = "a"; he_su_beamformer = 1; @@ -54,13 +55,60 @@ let 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"; + }; + + serverRadius = { + radius_server_clients = pkgs.writeText "clients" '' + 0.0.0.0/0 dgnum + ''; + radius_server_auth_port = 1812; + radius_server_ipv6 = 1; + }; + + localRadius = { + eap_server = 1; + eap_user_file = pkgs.writeText "user.db" '' + # anonymous login in phase 1 + * PEAP + # password based in the secure tunnel in phase 2 + "test" MSCHAPV2 "diamond dogs" [2] + ''; + + # DGNum CA certificate. + ca_cert = builtins.toFile "dgnum-test-ap-ca" ( + builtins.readFile ../../keys/certs/dgnum-test-ap-ca.crt + ); + # Server certificate for this AP. + server_cert = builtins.toFile "dgnum-ap-server" ( + builtins.readFile ../../keys/certs/dgnum-ap-server.crt + ); + private_key = builtins.toFile "dgnum-ap-server-pkey" ( + builtins.readFile ../../keys/certs/dgnum-ap-server.key.pem + ); + }; + + # externalRadius = { + # own_ip_addr = ""; + # nas_identifier = ""; + + # auth_server_addr = ""; + # auth_server_port = 1812; + # auth_server_shared_secret = "dgnum"; + # }; + mkWifiSta = params: interface: secrets: svc.hostapd.build { inherit interface; - params = params // { - inherit (secrets) ssid wpa_passphrase; - }; + package = pkgs.hostapd-radius; + params = params // secrets; }; in rec { @@ -72,6 +120,8 @@ rec { "${modulesPath}/ntp" "${modulesPath}/vlan" "${modulesPath}/bridge" + "${modulesPath}/jitter-rng" + "${modulesPath}/pki" ../../modules/dgn-access-control.nix # TODO: god that's so a fucking hack. (import "${modulesPath}/../devices/zyxel-nwa50ax").module @@ -79,6 +129,13 @@ rec { hostname = "ap01-prototype"; + security.pki = { + installCACerts = true; + certificateFiles = [ + ../../keys/certs/dgnum-test-ap-ca.crt + ]; + }; + # SSH keys are handled by the access control module. dgn-access-control.enable = true; users.root = { @@ -126,10 +183,12 @@ rec { }; # wlan0 is the 2.4GHz interface. - services.hostap-1 = mkWifiSta baseParams config.hardware.networkInterfaces.wlan0 secrets-1; + services.hostap-1 = mkWifiSta ( + baseParams // clientRadius // localRadius // serverRadius // radiusKeyMgmt + ) config.hardware.networkInterfaces.wlan0 secrets-1; # wlan1 is the 5GHz interface, e.g. AX capable. services.hostap-2 = mkWifiSta ( - baseParams // modernParams + baseParams // clientRadius // localRadius // serverRadius // radiusKeyMgmt // modernParams ) config.hardware.networkInterfaces.wlan1 secrets-2; defaultProfile.packages = with pkgs; [ diff --git a/npins/sources.json b/npins/sources.json index 84f9911b..d37fced5 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -9,6 +9,7 @@ }, "pre_releases": false, "version_upper_bound": null, + "release_prefix": null, "version": "0.15.0", "revision": "564595d0ad4be7277e07fa63b5a991b3c645655d", "url": "https://api.github.com/repos/ryantm/agenix/tarball/0.15.0", @@ -58,6 +59,7 @@ }, "pre_releases": false, "version_upper_bound": null, + "release_prefix": null, "version": "v1.6.0", "revision": "5eaf747af38dd272e1ab28a8ec4bd972424b07cf", "url": "https://api.github.com/repos/nix-community/disko/tarball/v1.6.0", @@ -71,6 +73,7 @@ }, "pre_releases": false, "version_upper_bound": null, + "release_prefix": null, "version": "v1.2.1", "revision": "66979725afe2164491be38ffff78460cc9b0ffd7", "url": null, @@ -82,10 +85,10 @@ "type": "Git", "url": "https://git.dgnum.eu/DGNum/liminix.git" }, - "branch": "main", - "revision": "7206fea4b4e9a5e50be91cce39c09da602cdb694", + "branch": "strong-tftp", + "revision": "a906301aebab47f11b2d2e762af8b65b8fc1040a", "url": null, - "hash": "0dd7r80skjamx1sppsl6mdmjhr355lbmc72g0l0356xs67mg8w5p" + "hash": "0c744qyjhcf6s474r4g6z5jww2dzgl857q320d9lm153ambz7rjh" }, "linkal": { "type": "Git", @@ -118,6 +121,7 @@ }, "pre_releases": false, "version_upper_bound": null, + "release_prefix": null, "version": "0.1.6", "revision": "ffb3dfa4c146d48300bd4fa625acfe48e091a734", "url": null, @@ -142,6 +146,7 @@ }, "pre_releases": false, "version_upper_bound": null, + "release_prefix": null, "version": "v0.5.0", "revision": "e11ba20945f4a867f09d84343c37328288f274b4", "url": null, @@ -162,8 +167,8 @@ "nixpkgs": { "type": "Channel", "name": "nixpkgs-unstable", - "url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.05pre622672.ad7efee13e0d/nixexprs.tar.xz", - "hash": "0ng26dp73sd5dffw8wl4pwfmrgp2p03xbp4l1lxwlhcw6874fk4l" + "url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.11pre670424.5de1564aed41/nixexprs.tar.xz", + "hash": "1m31bsq9mawjgbxzg4mihk9blfm419451vdsk30llbrj4w4s159w" }, "pre-commit-hooks": { "type": "Git", From 04cb0a9f045551897c3b72ea353a911ccbaa3090 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sat, 31 Aug 2024 22:22:00 +0200 Subject: [PATCH 11/28] feat(scripts): add liminix-oriented scripts - extraction for manual recovery via nandwrite - liminix rebuild to interactively develop the AP Signed-off-by: Ryan Lahfa --- .../extract-firmware-from-zyxel-nwa-fit.sh | 12 ++++++ scripts/liminix-rebuild.sh | 42 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100755 scripts/extract-firmware-from-zyxel-nwa-fit.sh create mode 100755 scripts/liminix-rebuild.sh diff --git a/scripts/extract-firmware-from-zyxel-nwa-fit.sh b/scripts/extract-firmware-from-zyxel-nwa-fit.sh new file mode 100755 index 00000000..12a8cd2b --- /dev/null +++ b/scripts/extract-firmware-from-zyxel-nwa-fit.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p ubootTools + +usage() { + echo "extract the firmware part to write it manually from a Zyxel NWA FIT image" + echo "$0 " +} + +ZYXEL_NWA_FIT="$1" +FIRMWARE_OUTPUT="$2" + +dumpimage -T flat_dt -p 0 $ZYXEL_NWA_FIT -o $FIRMWARE_OUTPUT diff --git a/scripts/liminix-rebuild.sh b/scripts/liminix-rebuild.sh new file mode 100755 index 00000000..1e36a84c --- /dev/null +++ b/scripts/liminix-rebuild.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +ssh_command=${SSH_COMMAND-ssh} + +reboot="reboot" + +case "$1" in + "--no-reboot") + unset reboot + shift + ;; + "--fast") + reboot="soft" + shift + ;; +esac + +target_host=$1 +shift + +if [ -z "$target_host" ] ; then + echo Usage: liminix-rebuild \[--no-reboot\] target-host params + exit 1 +fi + +if toplevel="$@"; then + echo systemConfiguration $toplevel + min-copy-closure $target_host $toplevel + $ssh_command $target_host $toplevel/bin/install + case "$reboot" in + reboot) + $ssh_command $target_host "sync; source /etc/profile; reboot" + ;; + soft) + $ssh_command $target_host $toplevel/bin/restart-services + ;; + *) + ;; + esac +else + echo Rebuild failed +fi From 270eb4b106778622c9989366966228db0f3e21b9 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sat, 31 Aug 2024 22:37:46 +0200 Subject: [PATCH 12/28] chore(ap01): cleanup Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index c894045c..1963b67a 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -5,13 +5,6 @@ ... }: let - # inherit (pkgs.liminix.services) - # oneshot - # longrun - # bundle - # target - # ; - # inherit (pkgs) writeText; svc = config.system.service; secrets-1 = { ssid = "DGNum 2G prototype (N)"; @@ -131,9 +124,7 @@ rec { security.pki = { installCACerts = true; - certificateFiles = [ - ../../keys/certs/dgnum-test-ap-ca.crt - ]; + certificateFiles = [ ../../keys/certs/dgnum-test-ap-ca.crt ]; }; # SSH keys are handled by the access control module. From afd92ab203c4ce35c5b6840956656718bd7689ad Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sat, 31 Aug 2024 22:38:07 +0200 Subject: [PATCH 13/28] feat(devshell): add kanidm & freeradius Signed-off-by: Ryan Lahfa --- default.nix | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/default.nix b/default.nix index 7655a8b0..4eb50110 100644 --- a/default.nix +++ b/default.nix @@ -75,16 +75,11 @@ in nixos-generators attic-client picocom - (callPackage (sources.liminix + "/pkgs/min-copy-closure") { - nix = pkgs.lix; - }) - (callPackage (sources.liminix + "/pkgs/min-collect-garbage") { - nix = pkgs.lix; - }) - (callPackage (sources.liminix + "/pkgs/tufted") - { - } - ) + kanidm # for remote SSO operations + freeradius # for radtest + (callPackage (sources.liminix + "/pkgs/min-copy-closure") { nix = pkgs.lix; }) + (callPackage (sources.liminix + "/pkgs/min-collect-garbage") { nix = pkgs.lix; }) + (callPackage (sources.liminix + "/pkgs/tufted") { }) (callPackage (sources.disko + "/package.nix") { }) (callPackage ./lib/colmena { colmena = import sources.colmena; }) ]) From 47231417cc62584167dad80e2c5ab149eab5721d Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 1 Sep 2024 17:20:37 +0200 Subject: [PATCH 14/28] feat(liminix-rebuild): support hive names directly Thanks @catvayor, I'm so dumb. Signed-off-by: Ryan Lahfa --- scripts/liminix-rebuild.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/liminix-rebuild.sh b/scripts/liminix-rebuild.sh index 1e36a84c..cf8e1005 100755 --- a/scripts/liminix-rebuild.sh +++ b/scripts/liminix-rebuild.sh @@ -23,7 +23,7 @@ if [ -z "$target_host" ] ; then exit 1 fi -if toplevel="$@"; then +if toplevel="$(nom-build $(colmena eval -E "{ nodes, ... }: nodes.$@.config.system.outputs.systemConfiguration" --instantiate))"; then echo systemConfiguration $toplevel min-copy-closure $target_host $toplevel $ssh_command $target_host $toplevel/bin/install From 4fb39070bbf63bcbc6515c72893edf10eab7a47e Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 1 Sep 2024 17:49:42 +0200 Subject: [PATCH 15/28] fix(sources): update to the latest version of Liminix With bridge fixes and many other things. Signed-off-by: Ryan Lahfa --- npins/sources.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/npins/sources.json b/npins/sources.json index d37fced5..f034faf5 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -85,10 +85,10 @@ "type": "Git", "url": "https://git.dgnum.eu/DGNum/liminix.git" }, - "branch": "strong-tftp", - "revision": "a906301aebab47f11b2d2e762af8b65b8fc1040a", + "branch": "main", + "revision": "4ff772639f9bb5d079a50b2b69f3ddc9053f2e9a", "url": null, - "hash": "0c744qyjhcf6s474r4g6z5jww2dzgl857q320d9lm153ambz7rjh" + "hash": "1jh2115ajh26362fazkmyhvv6zvp5z3yjynl91kgsvvld936169c" }, "linkal": { "type": "Git", From 0b94fb5ba74bffffffa14d9140643dc0d96cf4b0 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 1 Sep 2024 18:03:18 +0200 Subject: [PATCH 16/28] feat(ap01): external RADIUS + DHCPv4 + jitterRNGd + stable bridge + default route Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 133 ++++++++++++++++++------------- 1 file changed, 76 insertions(+), 57 deletions(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index 1963b67a..af4cecd4 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -5,12 +5,17 @@ ... }: 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-1 = { + # ssid = "DGNum 2G prototype (N)"; + # # wpa_passphrase = "diamond dogs"; + # }; secrets-2 = { ssid = "DGNum 5G prototype (AX)"; + # wpa_passphrase = "diamond dogs"; }; baseParams = { country_code = "FR"; @@ -57,57 +62,31 @@ let vlan_tagged_interface = "lan"; }; - serverRadius = { - radius_server_clients = pkgs.writeText "clients" '' - 0.0.0.0/0 dgnum - ''; - radius_server_auth_port = 1812; - radius_server_ipv6 = 1; + 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"; }; - localRadius = { - eap_server = 1; - eap_user_file = pkgs.writeText "user.db" '' - # anonymous login in phase 1 - * PEAP - # password based in the secure tunnel in phase 2 - "test" MSCHAPV2 "diamond dogs" [2] - ''; - - # DGNum CA certificate. - ca_cert = builtins.toFile "dgnum-test-ap-ca" ( - builtins.readFile ../../keys/certs/dgnum-test-ap-ca.crt - ); - # Server certificate for this AP. - server_cert = builtins.toFile "dgnum-ap-server" ( - builtins.readFile ../../keys/certs/dgnum-ap-server.crt - ); - private_key = builtins.toFile "dgnum-ap-server-pkey" ( - builtins.readFile ../../keys/certs/dgnum-ap-server.key.pem - ); - }; - - # externalRadius = { - # own_ip_addr = ""; - # nas_identifier = ""; - - # auth_server_addr = ""; - # auth_server_port = 1812; - # auth_server_shared_secret = "dgnum"; - # }; - 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" @@ -122,10 +101,8 @@ rec { hostname = "ap01-prototype"; - security.pki = { - installCACerts = true; - certificateFiles = [ ../../keys/certs/dgnum-test-ap-ca.crt ]; - }; + # Get moar random please + services.jitter = svc.jitter-rng.build { }; # SSH keys are handled by the access control module. dgn-access-control.enable = true; @@ -136,25 +113,66 @@ rec { passwd = "$6$jVXFFOp8HBYmgINR$lutB4kvw.W1jlXRby9ZYAgBitQ32RxQdYAGN.s2x4ris8J07vM6tzlRBQoeLELOIEMClDzbciQV0itfHQnTqd1"; }; - services.int = svc.bridge.primary.build { ifname = "int"; }; + services.int = svc.bridge.primary.build { + ifname = "int"; + macAddressFromInterface = config.hardware.networkInterfaces.lan; + }; services.bridge = svc.bridge.members.build { primary = services.int; members = with config.hardware.networkInterfaces; [ lan - wlan0 + # wlan0 wlan1 ]; }; - services.dhcpv4 = - let - iface = services.int; - in - svc.network.dhcp.client.build { interface = iface; }; + 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"; + }; + }; + + services.dhcpv4 = svc.network.dhcp.client.build { + interface = config.services.int; + dependencies = [ + config.services.hostname + config.services.bridge + ]; + }; + + 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} address)"; + via = "$(output ${services.dhcpv4} router)"; target = "default"; dependencies = [ services.dhcpv4 ]; }; @@ -166,6 +184,8 @@ rec { pools = { "pool.ntp.org" = [ "iburst" ]; }; + + dependencies = [ config.services.jitter ]; }; boot.tftp = { @@ -174,17 +194,16 @@ rec { }; # wlan0 is the 2.4GHz interface. - services.hostap-1 = mkWifiSta ( - baseParams // clientRadius // localRadius // serverRadius // radiusKeyMgmt - ) config.hardware.networkInterfaces.wlan0 secrets-1; + # services.hostap-1 = mkWifiSta ( + # baseParams // radiusKeyMgmt + # ) config.hardware.networkInterfaces.wlan0 secrets-1; # wlan1 is the 5GHz interface, e.g. AX capable. services.hostap-2 = mkWifiSta ( - baseParams // clientRadius // localRadius // serverRadius // radiusKeyMgmt // modernParams + baseParams // clientRadius // externalRadius // radiusKeyMgmt // modernParams ) config.hardware.networkInterfaces.wlan1 secrets-2; defaultProfile.packages = with pkgs; [ zyxel-bootconfig - iw min-collect-garbage mtdutils ]; From 45b106190ff5463646f99626f07585decac5b363 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 1 Sep 2024 18:04:56 +0200 Subject: [PATCH 17/28] feat(ap01): disable IPv6 Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index af4cecd4..036b92e1 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -157,19 +157,21 @@ rec { ]; }; - services.dhcpv6 = svc.dhcp6c.client.build { - interface = config.services.int; - dependencies = [ - config.services.hostname - config.services.bridge - ]; - }; + # 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.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)"; From adb843dd8b37d1254d734d050d03af5adba048d6 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Thu, 5 Sep 2024 14:58:38 +0200 Subject: [PATCH 18/28] feat(ap01): add ubus Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index 036b92e1..f8a6cf23 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -94,6 +94,7 @@ rec { "${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 @@ -103,6 +104,7 @@ rec { # 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; From 994e593d3b1af6fb65e57d04dd2513f263bdb11f Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Thu, 5 Sep 2024 14:58:44 +0200 Subject: [PATCH 19/28] chore(ap01): cleanup Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index f8a6cf23..ef8c3008 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -109,9 +109,6 @@ rec { # SSH keys are handled by the access control module. dgn-access-control.enable = true; users.root = { - # EDIT: choose a root password and then use - # "mkpasswd -m sha512crypt" to determine the hash. - # It should start wirh $6$. passwd = "$6$jVXFFOp8HBYmgINR$lutB4kvw.W1jlXRby9ZYAgBitQ32RxQdYAGN.s2x4ris8J07vM6tzlRBQoeLELOIEMClDzbciQV0itfHQnTqd1"; }; From 9bf83a60fe69a3ad11072f80f6e16e1995faf530 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Thu, 5 Sep 2024 14:59:16 +0200 Subject: [PATCH 20/28] fix(ap01): fix _one_ race condition when bridging the LAN The remaining is hostapd notification that the WLAN interface is ready to bridge. Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 15 +++++++++------ npins/sources.json | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index ef8c3008..a098d1cb 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -119,11 +119,14 @@ rec { services.bridge = svc.bridge.members.build { primary = services.int; - members = with config.hardware.networkInterfaces; [ - lan - # wlan0 - wlan1 - ]; + members = { + lan.member = config.hardware.networkInterfaces.lan; + wlan1 = { + member = config.hardware.networkInterfaces.wlan1; + # Bridge only once hostapd is ready. + dependencies = [ config.services.hostap-2 ]; + }; + }; }; services.resolvconf = oneshot rec { @@ -152,7 +155,7 @@ rec { interface = config.services.int; dependencies = [ config.services.hostname - config.services.bridge + config.services.bridge.components.lan ]; }; diff --git a/npins/sources.json b/npins/sources.json index f034faf5..9f81f042 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -86,9 +86,9 @@ "url": "https://git.dgnum.eu/DGNum/liminix.git" }, "branch": "main", - "revision": "4ff772639f9bb5d079a50b2b69f3ddc9053f2e9a", + "revision": "0fb671023c0571d936a568721c67819a23cf63c0", "url": null, - "hash": "1jh2115ajh26362fazkmyhvv6zvp5z3yjynl91kgsvvld936169c" + "hash": "0d7hyl89049flqvxzpvj938ma30fi3y58y4z6gjj2038v2vsd2f1" }, "linkal": { "type": "Git", From 337a71a169560da3fd6d3a243031e3bf2c17116b Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Thu, 5 Sep 2024 17:06:40 +0200 Subject: [PATCH 21/28] feat(scripts): add Android profile building via Nix Signed-off-by: Ryan Lahfa --- scripts/android-profile-template.xml | 62 ++++++++++++++++++++++++++++ scripts/build-android-profile.nix | 19 +++++++++ 2 files changed, 81 insertions(+) create mode 100644 scripts/android-profile-template.xml create mode 100644 scripts/build-android-profile.nix diff --git a/scripts/android-profile-template.xml b/scripts/android-profile-template.xml new file mode 100644 index 00000000..38ff8639 --- /dev/null +++ b/scripts/android-profile-template.xml @@ -0,0 +1,62 @@ + + + DGNumRadius + + + @SSID@ + + + ESS + auto + + + + WPA2 + AES + true + + + + + + 25 + 0 + + + + 25 + + + false + + + true + 0 + radius.dgnum.eu + + 26 + + false + + + @USERNAME@ + @PASSWORD@ + + + false + false + + + + + + + + + + diff --git a/scripts/build-android-profile.nix b/scripts/build-android-profile.nix new file mode 100644 index 00000000..8fdac9dd --- /dev/null +++ b/scripts/build-android-profile.nix @@ -0,0 +1,19 @@ +{ + pkgs ? import { }, + username, + domain ? "sso.dgnum.eu", + ssid ? "DGNum 5G prototype (AX)", + password, +}: +pkgs.runCommand "connection-${username}-android-profile.xml" + { + SSID = ssid; + USERNAME = "${username}@${domain}"; + PASSWORD = password; + } + '' + substitute ${./android-profile-template.xml} $out \ + --subst-var SSID \ + --subst-var USERNAME \ + --subst-var PASSWORD + '' From c0ec57ef2290fea20ff287b94f3154a63b79687e Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sat, 7 Sep 2024 21:14:16 +0200 Subject: [PATCH 22/28] fix(ap01): bridge only once the WLAN is in operational state It required a lot of technology, but hey, we now have it. Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index a098d1cb..37fed3ad 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -124,7 +124,7 @@ rec { wlan1 = { member = config.hardware.networkInterfaces.wlan1; # Bridge only once hostapd is ready. - dependencies = [ config.services.hostap-2 ]; + dependencies = [ config.services.hostap-2-ready ]; }; }; }; @@ -205,6 +205,10 @@ rec { 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 From 99902d2bb8f197804ac610daa6e151ab0a1799bf Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 8 Sep 2024 00:48:10 +0200 Subject: [PATCH 23/28] chore: upgrade liminix Signed-off-by: Ryan Lahfa --- npins/sources.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/npins/sources.json b/npins/sources.json index 9f81f042..5a70e35a 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -86,9 +86,9 @@ "url": "https://git.dgnum.eu/DGNum/liminix.git" }, "branch": "main", - "revision": "0fb671023c0571d936a568721c67819a23cf63c0", + "revision": "6970d811e87a3a99a093705cb089a5a63961cfe7", "url": null, - "hash": "0d7hyl89049flqvxzpvj938ma30fi3y58y4z6gjj2038v2vsd2f1" + "hash": "08fwry3zkhlkcl1lrqhhhqj3a47mgc41bvfv518zg8xhwzg7ifnz" }, "linkal": { "type": "Git", From 46d07da40468657d31450311c529f3633d9ae6ed Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 8 Sep 2024 00:50:29 +0200 Subject: [PATCH 24/28] fix(hive): misc fixes regarding the nixpkgs usage Previously, we were using actually, we fixed liminix and this file to ensure that we are instantiating the right nixpkgs. This helps to deal with unexpected mass rebuilds. Signed-off-by: Ryan Lahfa --- hive.nix | 61 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/hive.nix b/hive.nix index 71180d5e..139b9780 100644 --- a/hive.nix +++ b/hive.nix @@ -46,24 +46,27 @@ let inherit version; }; + mkNixpkgsConfigPerSystem = + system: _: + if system == "nixos" then + { } + else + (import "${sources.liminix}/devices/${system}").system + // { + overlays = [ (import "${sources.liminix}/overlay.nix") ]; + config = { + allowUnsupportedSystem = true; # mipsel + permittedInsecurePackages = [ + "python-2.7.18.8" # Python < 3 is needed for kernel backports. + ]; + }; + }; + # Instanciate a specialized version of nixpkgs mkSystemNixpkgs = system: version: let - args = - if system == "nixos" then - { } - else - (import "${sources.liminix}/devices/${system}").system - // { - overlays = [ (import "${sources.liminix}/overlay.nix") ]; - config = { - allowUnsupportedSystem = true; # mipsel - permittedInsecurePackages = [ - "python-2.7.18.8" # Python < 3 is needed for kernel backports. - ]; - }; - }; + args = mkNixpkgsConfigPerSystem system version; in import (mkNixpkgs' version) args; @@ -93,19 +96,31 @@ in { registry = { zyxel-nwa50ax = { - evalConfig = import "${sources.liminix}/lib/eval-config.nix" { nixpkgs = sources.nixos-unstable; }; + evalConfig = import "${sources.liminix}/lib/eval-config.nix" { + nixpkgs = sources.nixos-unstable; + }; defaults = _: { - nixpkgs.hostPlatform = { - config = "mipsel-unknown-linux-musl"; - gcc = { - abi = "32"; - arch = "mips32"; # mips32r2? + nixpkgs = { + source = sources.nixos-unstable; + config = { + allowUnsupportedSystem = true; # mipsel + permittedInsecurePackages = [ + "python-2.7.18.8" # Python < 3 is needed for kernel backports. + ]; }; + hostPlatform = { + config = "mipsel-unknown-linux-musl"; + gcc = { + abi = "32"; + arch = "mips32"; # mips32r2? + }; + }; + + # It's impure, but who cares? + # Can Flakes do that? + buildPlatform = builtins.currentSystem; }; - # It's impure, but who cares? - # Can Flakes do that? - nixpkgs.buildPlatform = builtins.currentSystem; }; }; From c08d6c464f7c34865a8e5d06bc252c582b253157 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 8 Sep 2024 00:47:05 +0200 Subject: [PATCH 25/28] feat(ap01): re-enable 2GHz Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index 37fed3ad..edb1e165 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -9,13 +9,11 @@ let inherit (pkgs.pseudofile) symlink dir; inherit (pkgs) serviceFns; svc = config.system.service; - # secrets-1 = { - # ssid = "DGNum 2G prototype (N)"; - # # wpa_passphrase = "diamond dogs"; - # }; + secrets-1 = { + ssid = "DGNum 2G prototype (N)"; + }; secrets-2 = { ssid = "DGNum 5G prototype (AX)"; - # wpa_passphrase = "diamond dogs"; }; baseParams = { country_code = "FR"; @@ -121,6 +119,11 @@ rec { 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. @@ -198,9 +201,12 @@ rec { }; # wlan0 is the 2.4GHz interface. - # services.hostap-1 = mkWifiSta ( - # baseParams // radiusKeyMgmt - # ) config.hardware.networkInterfaces.wlan0 secrets-1; + 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 From 4ed0c435ba9070087cf3a7011a19ef244061a560 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 8 Sep 2024 00:47:24 +0200 Subject: [PATCH 26/28] feat(ap01): write nixpkgs version in /etc It's useful for debugging. We should also track our own revisions at some point. Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index edb1e165..380b16d9 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -151,6 +151,11 @@ rec { filesystem = dir { etc = dir { "resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf"; + "nixpkgs.version" = { + type = "f"; + file = "${pkgs.lib.version}"; + mode = "0444"; + }; }; }; From d29deeae56ad2a98d73490d3c2e0bcb5e6a71d11 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 8 Sep 2024 00:48:01 +0200 Subject: [PATCH 27/28] feat(ap01): use levitation for mass rebuilds 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 --- machines/ap01/_configuration.nix | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index 380b16d9..e1e6d2b8 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -224,6 +224,36 @@ rec { defaultProfile.packages = with pkgs; [ zyxel-bootconfig min-collect-garbage - mtdutils + 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; + }; + }) ]; } From ed285ba79d94d5082dbe8ffc22fb68a95036776d Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 8 Sep 2024 00:48:56 +0200 Subject: [PATCH 28/28] feat(scripts/liminix): fail HARD and support root prefixes Now that we possess the levitation technology, it's necessary to support root prefixes for rebuild otherwise we will just overwrite our RAM disk configuration. Also, to avoid any issue, let's fail hard and avoid rebooting while being in levitation for nothing. Signed-off-by: Ryan Lahfa --- scripts/liminix-rebuild.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/liminix-rebuild.sh b/scripts/liminix-rebuild.sh index cf8e1005..f07cc124 100755 --- a/scripts/liminix-rebuild.sh +++ b/scripts/liminix-rebuild.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash +set -Eeuo pipefail ssh_command=${SSH_COMMAND-ssh} +root_prefix=${ROOT_PREFIX-/} reboot="reboot" @@ -24,9 +26,10 @@ if [ -z "$target_host" ] ; then fi if toplevel="$(nom-build $(colmena eval -E "{ nodes, ... }: nodes.$@.config.system.outputs.systemConfiguration" --instantiate))"; then - echo systemConfiguration $toplevel - min-copy-closure $target_host $toplevel - $ssh_command $target_host $toplevel/bin/install + echo systemConfiguration $toplevel aimed at $root_prefix + sleep 3 + min-copy-closure --root "$root_prefix" $target_host $toplevel + $ssh_command $target_host "$root_prefix/$toplevel/bin/install" "$root_prefix" case "$reboot" in reboot) $ssh_command $target_host "sync; source /etc/profile; reboot"