Compare commits

...

28 commits

Author SHA1 Message Date
ed285ba79d feat(scripts/liminix): fail HARD and support root prefixes
Some checks failed
Check meta / check_meta (pull_request) Failing after 17s
lint / check (push) Successful in 31s
build configuration / build_compute01 (pull_request) Failing after 52s
build configuration / build_storage01 (pull_request) Failing after 52s
build configuration / build_vault01 (pull_request) Failing after 53s
Check meta / check_dns (pull_request) Failing after 1m6s
build configuration / build_web01 (pull_request) Failing after 53s
build configuration / build_web02 (pull_request) Failing after 41s
build configuration / build_rescue01 (pull_request) Failing after 30s
build configuration / push_to_cache (pull_request) Has been skipped
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 <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
d29deeae56 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 <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
4ed0c435ba 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 <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
c08d6c464f feat(ap01): re-enable 2GHz
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
46d07da404 fix(hive): misc fixes regarding the nixpkgs usage
Previously, we were using <nixpkgs> 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 <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
99902d2bb8 chore: upgrade liminix
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-08 00:48:12 +02:00
c0ec57ef22 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 <ryan@dgnum.eu>
2024-09-07 21:14:27 +02:00
337a71a169 feat(scripts): add Android profile building via Nix
Some checks failed
lint / check (push) Successful in 30s
Check meta / check_meta (pull_request) Failing after 48s
build configuration / build_compute01 (pull_request) Failing after 49s
build configuration / build_storage01 (pull_request) Failing after 50s
build configuration / build_vault01 (pull_request) Failing after 50s
Check meta / check_dns (pull_request) Failing after 1m4s
build configuration / build_web01 (pull_request) Failing after 40s
build configuration / build_rescue01 (pull_request) Failing after 34s
build configuration / build_web02 (pull_request) Failing after 35s
build configuration / push_to_cache (pull_request) Has been skipped
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-05 17:06:40 +02:00
9bf83a60fe fix(ap01): fix _one_ race condition when bridging the LAN
Some checks failed
Check meta / check_meta (pull_request) Failing after 17s
lint / check (push) Successful in 28s
build configuration / build_compute01 (pull_request) Failing after 43s
build configuration / build_storage01 (pull_request) Failing after 43s
build configuration / build_vault01 (pull_request) Failing after 45s
build configuration / build_web01 (pull_request) Failing after 34s
Check meta / check_dns (pull_request) Failing after 1m3s
build configuration / build_web02 (pull_request) Failing after 41s
build configuration / build_rescue01 (pull_request) Failing after 41s
build configuration / push_to_cache (pull_request) Has been skipped
The remaining is hostapd notification that the WLAN interface is ready
to bridge.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-05 14:59:16 +02:00
994e593d3b chore(ap01): cleanup
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-05 14:58:44 +02:00
adb843dd8b feat(ap01): add ubus
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-05 14:58:38 +02:00
45b106190f feat(ap01): disable IPv6
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-01 18:08:41 +02:00
0b94fb5ba7 feat(ap01): external RADIUS + DHCPv4 + jitterRNGd + stable bridge + default route
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-01 18:08:41 +02:00
4fb39070bb fix(sources): update to the latest version of Liminix
With bridge fixes and many other things.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-01 18:08:41 +02:00
47231417cc feat(liminix-rebuild): support hive names directly
Some checks failed
Check meta / check_meta (pull_request) Failing after 20s
build configuration / build_vault01 (pull_request) Failing after 22s
build configuration / build_compute01 (pull_request) Failing after 22s
lint / check (push) Successful in 28s
build configuration / build_storage01 (pull_request) Failing after 26s
build configuration / build_web01 (pull_request) Failing after 19s
build configuration / build_rescue01 (pull_request) Failing after 21s
build configuration / build_web02 (pull_request) Failing after 21s
build configuration / push_to_cache (pull_request) Has been skipped
Check meta / check_dns (pull_request) Failing after 1m0s
Thanks @catvayor, I'm so dumb.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-01 17:20:37 +02:00
afd92ab203 feat(devshell): add kanidm & freeradius
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:38:07 +02:00
270eb4b106 chore(ap01): cleanup
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:37:46 +02:00
04cb0a9f04 feat(scripts): add liminix-oriented scripts
Some checks failed
lint / check (push) Successful in 24s
Check meta / check_meta (pull_request) Failing after 20s
build configuration / build_storage01 (pull_request) Failing after 42s
build configuration / build_compute01 (pull_request) Failing after 43s
build configuration / build_vault01 (pull_request) Failing after 42s
Check meta / check_dns (pull_request) Failing after 1m3s
build configuration / build_web01 (pull_request) Failing after 38s
build configuration / build_web02 (pull_request) Failing after 39s
build configuration / build_rescue01 (pull_request) Failing after 38s
build configuration / push_to_cache (pull_request) Has been skipped
- extraction for manual recovery via nandwrite
- liminix rebuild to interactively develop the AP

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:23:04 +02:00
c4d9d6d000 feat(ap01): enable fully RADIUS via internal RADIUS server
This adds two public keys.

For the private keys, heh…

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:23:04 +02:00
be1673c6aa feat(devshell): add liminix-related tools
serial console, deployment tools and TFTP tool

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:20:24 +02:00
8b66b2b7c3 feat: add access control for APs via our custom modules
Some checks failed
Check meta / check_meta (push) Failing after 17s
Check meta / check_meta (pull_request) Failing after 18s
lint / check (push) Successful in 24s
build configuration / build_compute01 (pull_request) Failing after 38s
build configuration / build_storage01 (pull_request) Failing after 35s
Check meta / check_dns (push) Failing after 1m9s
Check meta / check_dns (pull_request) Failing after 59s
build configuration / build_vault01 (pull_request) Failing after 36s
build configuration / build_web01 (pull_request) Failing after 35s
build configuration / build_web02 (pull_request) Failing after 40s
build configuration / build_rescue01 (pull_request) Failing after 33s
build configuration / push_to_cache (pull_request) Has been skipped
It works!

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-22 18:45:40 +02:00
3ed6ecba31 feat: ensure that colmena repl can evaluate nodes.ap01
Some checks failed
lint / check (push) Successful in 49s
Check meta / check_meta (pull_request) Failing after 16s
Check meta / check_dns (pull_request) Failing after 58s
build configuration / build_vault01 (pull_request) Failing after 1m2s
build configuration / build_storage01 (pull_request) Failing after 1m5s
build configuration / build_compute01 (pull_request) Failing after 1m16s
build configuration / build_web02 (pull_request) Failing after 36s
build configuration / build_rescue01 (pull_request) Failing after 36s
build configuration / build_web01 (pull_request) Failing after 36s
build configuration / push_to_cache (pull_request) Has been skipped
Bump to latest Liminix and use the new `defaults` function.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-22 15:28:34 +02:00
5a8fe24dce feat: achieve custom evaluation in the framework
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-05-24 18:46:13 +02:00
0a948e6148 feat: Specialize nixpkgs as a function of the system 2024-05-24 18:46:13 +02:00
41ca207b41 feat: wip! wip! wip! 2024-05-24 18:46:01 +02:00
aa6b082b81 feat: enable liminix-rebuild
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-05-24 18:46:01 +02:00
17b2345a02 feat: add liminix-rebuild in the shell
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-05-24 18:46:01 +02:00
fde8f66ea7 feat: init Liminix evaluation system
Very rudimentary; undocumented, untested in production. This is for testing purposes.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-05-24 18:46:01 +02:00
18 changed files with 662 additions and 87 deletions

View file

@ -37,7 +37,6 @@
let let
sources = import ./npins; sources = import ./npins;
pkgs = import sources.nixpkgs { }; pkgs = import sources.nixpkgs { };
pre-commit-check = (import sources.pre-commit-hooks).run { pre-commit-check = (import sources.pre-commit-hooks).run {
src = ./.; src = ./.;
@ -71,18 +70,19 @@ in
name = "dgnum-infra"; name = "dgnum-infra";
packages = packages =
( (with pkgs; [
with pkgs; npins
[ nixos-generators
npins attic-client
nixos-generators picocom
attic-client kanidm # for remote SSO operations
] freeradius # for radtest
++ (builtins.map (p: callPackage p { }) [ (callPackage (sources.liminix + "/pkgs/min-copy-closure") { nix = pkgs.lix; })
(sources.disko + "/package.nix") (callPackage (sources.liminix + "/pkgs/min-collect-garbage") { nix = pkgs.lix; })
./lib/colmena (callPackage (sources.liminix + "/pkgs/tufted") { })
]) (callPackage (sources.disko + "/package.nix") { })
) (callPackage ./lib/colmena { colmena = import sources.colmena; })
])
++ (import ./scripts { inherit pkgs; }); ++ (import ./scripts { inherit pkgs; });
shellHook = '' shellHook = ''

169
hive.nix
View file

@ -2,6 +2,7 @@ let
sources = import ./npins; sources = import ./npins;
lib = import (sources.nix-lib + "/src/trivial.nix"); lib = import (sources.nix-lib + "/src/trivial.nix");
lib' = (import sources.nixos-unstable { }).lib;
patch = import sources.nix-patches { patchFile = ./patches; }; patch = import sources.nix-patches { patchFile = ./patches; };
@ -14,15 +15,25 @@ let
"_configuration.nix" "_configuration.nix"
"_hardware-configuration.nix" "_hardware-configuration.nix"
]; ];
deployment.systemType = systemType node;
}; };
nixpkgs' = import ./meta/nixpkgs.nix; nixpkgs' = import ./meta/nixpkgs.nix;
# All supported nixpkgs versions, instanciated # 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, # Get the configured nixos version for the node,
# defaulting to the one defined in meta/nixpkgs # 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 # Builds a patched version of nixpkgs, only as the source
mkNixpkgs' = mkNixpkgs' =
@ -35,67 +46,129 @@ let
inherit version; inherit version;
}; };
# Instanciates the required nixpkgs version mkNixpkgsConfigPerSystem =
mkNixpkgs = version: import (mkNixpkgs' version) { }; 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 # Function to create arguments based on the node
# #
mkArgs = node: rec { mkArgs =
lib = import sources.nix-lib { node:
inherit (nixpkgs.${version node}) lib; 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 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 = { meta = {
nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${version n}) nodes; nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${system n}.${version n}) nodes;
specialArgs = { specialArgs = {
inherit nixpkgs sources; inherit sources;
}; };
nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes; 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) // (lib.mapSingleFuse mkNode nodes)

View file

@ -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-----

View file

@ -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-----

1
liminix-rebuild.nix Normal file
View file

@ -0,0 +1 @@
{ liminix-system }: (import ./liminix-hive.nix { }).${liminix-system}.primary

View file

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

View file

@ -0,0 +1 @@
{ }

View file

@ -1,10 +1,23 @@
{ {
# Default version of nixpkgs to use versions = {
default = "23.11"; # Default version of nixpkgs to use
default = "23.11";
# Supported nixpkgs versions # Supported nixpkgs versions
supported = [ supported = [
"unstable" "unstable"
"23.11" "23.11"
]; ];
};
systems = {
# Default target system
default = "nixos";
# Supported target systems
supported = [
"nixos"
"zyxel-nwa50ax"
];
};
} }

View file

@ -86,4 +86,12 @@
stateVersion = "23.11"; stateVersion = "23.11";
vm-cluster = "Hyperviseur Luj"; vm-cluster = "Hyperviseur Luj";
}; };
# Access points definition
ap01 = {
site = "unknown";
adminGroups = [ "fai" ];
system = "zyxel-nwa50ax";
};
} }

View file

@ -11,6 +11,7 @@ let
inherit (lib.types) inherit (lib.types)
attrs attrs
attrsOf attrsOf
enum
ints ints
listOf listOf
nullOr nullOr
@ -35,6 +36,7 @@ let
}; };
org = config.organization; org = config.organization;
nixpkgs = import ./nixpkgs.nix;
in in
{ {
@ -124,8 +126,8 @@ in
}; };
nixpkgs = mkOption { nixpkgs = mkOption {
type = str; type = enum nixpkgs.versions.supported;
inherit (import ./nixpkgs.nix) default; inherit (nixpkgs.versions) default;
description = '' description = ''
Version of nixpkgs to use. Version of nixpkgs to use.
''; '';
@ -167,6 +169,14 @@ in
default = null; default = null;
description = "VM cluster where the VM is located"; 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 = { config = {

View file

@ -87,6 +87,12 @@
"fai" "fai"
]; ];
# AP administration DGNum
ap.adminGroups = [
"root"
"fai"
];
# Videos DGNum # Videos DGNum
peertube.admins = [ "thubrecht" ]; peertube.admins = [ "thubrecht" ];
}; };

View file

@ -44,6 +44,7 @@ let
mkDefault mkDefault
mkEnableOption mkEnableOption
mkIf mkIf
mkMerge
mkOption mkOption
types types
@ -78,12 +79,20 @@ in
}; };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable (mkMerge [
# Admins have root access to the node {
dgn-access-control.users.root = mkDefault admins; # 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; (mkIf (nodeMeta.system == "nixos") {
}) cfg.users; 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;
})
]);
} }

View file

@ -42,6 +42,7 @@ let
builtins.fetchGit { builtins.fetchGit {
inherit (repository) url; inherit (repository) url;
rev = revision; rev = revision;
allRefs = true;
# hash = hash; # hash = hash;
}; };

View file

@ -9,6 +9,7 @@
}, },
"pre_releases": false, "pre_releases": false,
"version_upper_bound": null, "version_upper_bound": null,
"release_prefix": null,
"version": "0.15.0", "version": "0.15.0",
"revision": "564595d0ad4be7277e07fa63b5a991b3c645655d", "revision": "564595d0ad4be7277e07fa63b5a991b3c645655d",
"url": "https://api.github.com/repos/ryantm/agenix/tarball/0.15.0", "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", "url": "https://github.com/zhaofengli/attic/archive/4dbdbee45728d8ce5788db6461aaaa89d98081f0.tar.gz",
"hash": "1iri77pbf0gvas93zra29qy1c3l61n97z84xblqxmmhsxvljzvnh" "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": { "disko": {
"type": "GitRelease", "type": "GitRelease",
"repository": { "repository": {
@ -47,6 +59,7 @@
}, },
"pre_releases": false, "pre_releases": false,
"version_upper_bound": null, "version_upper_bound": null,
"release_prefix": null,
"version": "v1.6.0", "version": "v1.6.0",
"revision": "5eaf747af38dd272e1ab28a8ec4bd972424b07cf", "revision": "5eaf747af38dd272e1ab28a8ec4bd972424b07cf",
"url": "https://api.github.com/repos/nix-community/disko/tarball/v1.6.0", "url": "https://api.github.com/repos/nix-community/disko/tarball/v1.6.0",
@ -60,6 +73,7 @@
}, },
"pre_releases": false, "pre_releases": false,
"version_upper_bound": null, "version_upper_bound": null,
"release_prefix": null,
"version": "v1.2.1", "version": "v1.2.1",
"revision": "66979725afe2164491be38ffff78460cc9b0ffd7", "revision": "66979725afe2164491be38ffff78460cc9b0ffd7",
"url": null, "url": null,
@ -68,14 +82,13 @@
"liminix": { "liminix": {
"type": "Git", "type": "Git",
"repository": { "repository": {
"type": "GitHub", "type": "Git",
"owner": "RaitoBezarius", "url": "https://git.dgnum.eu/DGNum/liminix.git"
"repo": "liminix"
}, },
"branch": "nwa50ax", "branch": "main",
"revision": "a4aa10dcc30225a8bb8eb465abfe908629175f2c", "revision": "6970d811e87a3a99a093705cb089a5a63961cfe7",
"url": "https://github.com/RaitoBezarius/liminix/archive/a4aa10dcc30225a8bb8eb465abfe908629175f2c.tar.gz", "url": null,
"hash": "1m1sc6agg5z65lmyjl48i7sddlwm8d0zgvs8z81iammfy4jpy7qd" "hash": "08fwry3zkhlkcl1lrqhhhqj3a47mgc41bvfv518zg8xhwzg7ifnz"
}, },
"linkal": { "linkal": {
"type": "Git", "type": "Git",
@ -108,6 +121,7 @@
}, },
"pre_releases": false, "pre_releases": false,
"version_upper_bound": null, "version_upper_bound": null,
"release_prefix": null,
"version": "0.1.6", "version": "0.1.6",
"revision": "ffb3dfa4c146d48300bd4fa625acfe48e091a734", "revision": "ffb3dfa4c146d48300bd4fa625acfe48e091a734",
"url": null, "url": null,
@ -132,6 +146,7 @@
}, },
"pre_releases": false, "pre_releases": false,
"version_upper_bound": null, "version_upper_bound": null,
"release_prefix": null,
"version": "v0.5.0", "version": "v0.5.0",
"revision": "e11ba20945f4a867f09d84343c37328288f274b4", "revision": "e11ba20945f4a867f09d84343c37328288f274b4",
"url": null, "url": null,
@ -152,8 +167,8 @@
"nixpkgs": { "nixpkgs": {
"type": "Channel", "type": "Channel",
"name": "nixpkgs-unstable", "name": "nixpkgs-unstable",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.05pre622672.ad7efee13e0d/nixexprs.tar.xz", "url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.11pre670424.5de1564aed41/nixexprs.tar.xz",
"hash": "0ng26dp73sd5dffw8wl4pwfmrgp2p03xbp4l1lxwlhcw6874fk4l" "hash": "1m31bsq9mawjgbxzg4mihk9blfm419451vdsk30llbrj4w4s159w"
}, },
"pre-commit-hooks": { "pre-commit-hooks": {
"type": "Git", "type": "Git",

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="US-ASCII"?>
<WLANProfile xmlns="https://www.microsoft.com/networking/WLAN/profile/v1">
<name>DGNumRadius</name>
<SSIDConfig>
<SSID>
<name>@SSID@</name>
</SSID>
</SSIDConfig>
<connectionType>ESS</connectionType>
<connectionMode>auto</connectionMode>
<MSM>
<security>
<authEncryption>
<authentication>WPA2</authentication>
<encryption>AES</encryption>
<useOneX>true</useOneX>
</authEncryption>
<OneX xmlns="https://www.microsoft.com/networking/OneX/v1">
<EAPConfig>
<EapHostConfig xmlns="https://www.microsoft.com/provisioning/EapHostConfig"
xmlns:eapCommon="https://www.microsoft.com/provisioning/EapCommon"
xmlns:baseEap="https://www.microsoft.com/provisioning/BaseEapMethodConfig">
<EapMethod>
<eapCommon:Type>25</eapCommon:Type>
<eapCommon:AuthorId>0</eapCommon:AuthorId>
</EapMethod>
<Config xmlns:baseEap="https://www.microsoft.com/provisioning/BaseEapConnectionPropertiesV1"
xmlns:msPeap="https://www.microsoft.com/provisioning/MsPeapConnectionPropertiesV1"
xmlns:msChapV2="https://www.microsoft.com/provisioning/MsChapV2ConnectionPropertiesV1"
xmlns:msChapV2User="https://www.microsoft.com/provisioning/MsChapV2UserPropertiesV1">
<baseEap:Eap>
<baseEap:Type>25</baseEap:Type>
<msPeap:EapType>
<msPeap:ServerValidation>
<msPeap:DisableUserPromptForServerValidation>false</msPeap:DisableUserPromptForServerValidation>
<msPeap:TrustedRootCA />
</msPeap:ServerValidation>
<msPeap:FastReconnect>true</msPeap:FastReconnect>
<msPeap:InnerEapOptional>0</msPeap:InnerEapOptional>
<msPeap:ServerNames>radius.dgnum.eu</msPeap:ServerNames>
<baseEap:Eap>
<baseEap:Type>26</baseEap:Type>
<msChapV2:EapType>
<msChapV2:UseWinLogonCredentials>false</msChapV2:UseWinLogonCredentials>
</msChapV2:EapType>
<msChapV2User:EapType>
<msChapV2User:Username>@USERNAME@</msChapV2User:Username>
<msChapV2User:Password>@PASSWORD@</msChapV2User:Password>
</msChapV2User>
</baseEap:Eap>
<msPeap:EnableQuarantineChecks>false</msPeap:EnableQuarantineChecks>
<msPeap:RequireCryptoBinding>false</msPeap:RequireCryptoBinding>
<msPeap:PeapExtensions />
</msPeap:EapType>
</baseEap:Eap>
</Config>
</EapHostConfig>
</EAPConfig>
</OneX>
</security>
</MSM>
</WLANProfile>

View file

@ -0,0 +1,19 @@
{
pkgs ? import <nixpkgs> { },
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
''

View file

@ -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_image_path> <firmware_output_file>"
}
ZYXEL_NWA_FIT="$1"
FIRMWARE_OUTPUT="$2"
dumpimage -T flat_dt -p 0 $ZYXEL_NWA_FIT -o $FIRMWARE_OUTPUT

45
scripts/liminix-rebuild.sh Executable file
View file

@ -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