diff --git a/default.nix b/default.nix index d04dfadb..4eb50110 100644 --- a/default.nix +++ b/default.nix @@ -37,7 +37,6 @@ let sources = import ./npins; pkgs = import sources.nixpkgs { }; - pre-commit-check = (import sources.pre-commit-hooks).run { src = ./.; @@ -71,18 +70,19 @@ in name = "dgnum-infra"; packages = - ( - with pkgs; - [ - npins - nixos-generators - attic-client - ] - ++ (builtins.map (p: callPackage p { }) [ - (sources.disko + "/package.nix") - ./lib/colmena - ]) - ) + (with pkgs; [ + npins + nixos-generators + attic-client + picocom + 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; }) + ]) ++ (import ./scripts { inherit pkgs; }); shellHook = '' diff --git a/hive.nix b/hive.nix index 1f539193..139b9780 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,15 +15,25 @@ let "_configuration.nix" "_hardware-configuration.nix" ]; + + deployment.systemType = systemType node; }; 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; + 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' = @@ -35,67 +46,129 @@ let inherit version; }; - # Instanciates the required nixpkgs version - mkNixpkgs = version: import (mkNixpkgs' 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 = mkNixpkgsConfigPerSystem system version; + 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; + + keysRoot = ./keys; + }; + + meta = (import ./meta) lib; + + nodeMeta = meta.nodes.${node}; }; - - meta = (import ./meta) lib; - - nodeMeta = meta.nodes.${node}; - }; in { + registry = { + zyxel-nwa50ax = { + evalConfig = import "${sources.liminix}/lib/eval-config.nix" { + nixpkgs = sources.nixos-unstable; + }; + + defaults = _: { + 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; + }; + }; + }; + + 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; + }; + }; + }; + }; + meta = { - nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${version n}) nodes; + nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${system n}.${version n}) nodes; specialArgs = { - inherit nixpkgs sources; + inherit sources; }; nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes; }; - - defaults = - { name, nodeMeta, ... }: - { - # 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; - }; - }; } // (lib.mapSingleFuse mkNode nodes) 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/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 diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix new file mode 100644 index 00000000..e1e6d2b8 --- /dev/null +++ b/machines/ap01/_configuration.nix @@ -0,0 +1,259 @@ +{ + 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; + }; + }) + ]; +} 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/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..d538a1b7 100644 --- a/meta/nodes.nix +++ b/meta/nodes.nix @@ -86,4 +86,12 @@ stateVersion = "23.11"; vm-cluster = "Hyperviseur Luj"; }; + + # Access points definition + ap01 = { + site = "unknown"; + adminGroups = [ "fai" ]; + + 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 = { 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; + }) + ]); } 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 3db11630..5a70e35a 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", @@ -38,6 +39,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": "1037471d800d3db42ec85b89787bec5472f5e574", + "url": null, + "hash": "0k287292yr78zymdglppa8jd0b4kh0x277d4bycwcdsqprw00a4x" + }, "disko": { "type": "GitRelease", "repository": { @@ -47,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", @@ -60,6 +73,7 @@ }, "pre_releases": false, "version_upper_bound": null, + "release_prefix": null, "version": "v1.2.1", "revision": "66979725afe2164491be38ffff78460cc9b0ffd7", "url": null, @@ -68,14 +82,13 @@ "liminix": { "type": "Git", "repository": { - "type": "GitHub", - "owner": "RaitoBezarius", - "repo": "liminix" + "type": "Git", + "url": "https://git.dgnum.eu/DGNum/liminix.git" }, - "branch": "nwa50ax", - "revision": "a4aa10dcc30225a8bb8eb465abfe908629175f2c", - "url": "https://github.com/RaitoBezarius/liminix/archive/a4aa10dcc30225a8bb8eb465abfe908629175f2c.tar.gz", - "hash": "1m1sc6agg5z65lmyjl48i7sddlwm8d0zgvs8z81iammfy4jpy7qd" + "branch": "main", + "revision": "6970d811e87a3a99a093705cb089a5a63961cfe7", + "url": null, + "hash": "08fwry3zkhlkcl1lrqhhhqj3a47mgc41bvfv518zg8xhwzg7ifnz" }, "linkal": { "type": "Git", @@ -108,6 +121,7 @@ }, "pre_releases": false, "version_upper_bound": null, + "release_prefix": null, "version": "0.1.6", "revision": "ffb3dfa4c146d48300bd4fa625acfe48e091a734", "url": null, @@ -132,6 +146,7 @@ }, "pre_releases": false, "version_upper_bound": null, + "release_prefix": null, "version": "v0.5.0", "revision": "e11ba20945f4a867f09d84343c37328288f274b4", "url": null, @@ -152,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", 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 + '' 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..f07cc124 --- /dev/null +++ b/scripts/liminix-rebuild.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +ssh_command=${SSH_COMMAND-ssh} +root_prefix=${ROOT_PREFIX-/} + +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="$(nom-build $(colmena eval -E "{ nodes, ... }: nodes.$@.config.system.outputs.systemConfiguration" --instantiate))"; then + 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" + ;; + soft) + $ssh_command $target_host $toplevel/bin/restart-services + ;; + *) + ;; + esac +else + echo Rebuild failed +fi