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