WIP: ap01: towards our VLAN model #181
8 changed files with 143 additions and 54 deletions
|
@ -116,6 +116,13 @@ in
|
||||||
pkgs.freeradius
|
pkgs.freeradius
|
||||||
pkgs.picocom # for serial access
|
pkgs.picocom # for serial access
|
||||||
|
|
||||||
|
# Daemon-less copy closure for Liminix systems.
|
||||||
|
(pkgs.callPackage (sources.liminix + "/pkgs/min-copy-closure") { nix = pkgs.lix; })
|
||||||
|
# Daemon-less garbage collection for Liminix systems.
|
||||||
|
(pkgs.callPackage (sources.liminix + "/pkgs/min-collect-garbage") { nix = pkgs.lix; })
|
||||||
|
# TFTP server, friendly for Nix builds.
|
||||||
|
(pkgs.callPackage (sources.liminix + "/pkgs/tufted") { })
|
||||||
|
|
||||||
(pkgs.callPackage ./lib/colmena {
|
(pkgs.callPackage ./lib/colmena {
|
||||||
colmena = pkgs.callPackage "${sources.colmena}/package.nix" { };
|
colmena = pkgs.callPackage "${sources.colmena}/package.nix" { };
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,16 +3,18 @@ let
|
||||||
svc = config.system.service;
|
svc = config.system.service;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
services.dhcpv4 = svc.network.dhcp.client.build {
|
services.init-dhcpv4 = svc.network.dhcp.client.build {
|
||||||
interface = config.services.int;
|
interface = config.services.int;
|
||||||
dependencies = [
|
dependencies = [
|
||||||
config.services.bridge.components.lan
|
config.services.bridge.components.lan
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.defaultroute4 = svc.network.route.build {
|
services.init-defaultroute4 = svc.network.route.build {
|
||||||
via = "$(output ${config.services.dhcpv4} router)";
|
via = "$(output ${config.services.init-dhcpv4} router)";
|
||||||
target = "default";
|
target = "default";
|
||||||
dependencies = [ config.services.dhcpv4 ];
|
dependencies = [ config.services.init-dhcpv4 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# TODO: ensure SLAAC for admin-vlan.
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,18 @@ in
|
||||||
# TODO: support dynamic reconfiguration once we are in the target VLAN?
|
# TODO: support dynamic reconfiguration once we are in the target VLAN?
|
||||||
services.resolvconf = oneshot rec {
|
services.resolvconf = oneshot rec {
|
||||||
name = "resolvconf";
|
name = "resolvconf";
|
||||||
|
# TODO: imho, DNS should be static and provided by the router?
|
||||||
up = ''
|
up = ''
|
||||||
. ${serviceFns}
|
. ${serviceFns}
|
||||||
( in_outputs ${name}
|
( in_outputs ${name}
|
||||||
for i in $(output ${config.services.dhcpv4} dns); do
|
for i in $(output ${config.services.init-dhcpv4} dns); do
|
||||||
echo "nameserver $i" >> resolv.conf
|
echo "nameserver $i" >> resolv.conf
|
||||||
done
|
done
|
||||||
)
|
)
|
||||||
'';
|
'';
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
config.services.dhcpv4
|
config.services.init-dhcpv4
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,37 +3,41 @@ let
|
||||||
svc = config.system.service;
|
svc = config.system.service;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
services.int = svc.bridge.primary.build {
|
# Our bridging is a bit complicated, therefore, we need iproute2.
|
||||||
ifname = "int";
|
programs.iproute2.enable = true;
|
||||||
macAddressFromInterface = config.hardware.networkInterfaces.lan;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.bridge = svc.bridge.members.build {
|
services = {
|
||||||
primary = config.services.int;
|
int = svc.bridge.primary.build {
|
||||||
members = {
|
ifname = "int";
|
||||||
lan.member = config.hardware.networkInterfaces.lan;
|
macAddressFromInterface = config.hardware.networkInterfaces.lan;
|
||||||
wlan0 = {
|
untagged = {
|
||||||
member = config.hardware.networkInterfaces.wlan0;
|
enable = true;
|
||||||
# Bridge only once hostapd is ready.
|
pvid = 1;
|
||||||
dependencies = [ config.services.hostap-1-ready ];
|
default-pvid = 1;
|
||||||
};
|
|
||||||
wlan1 = {
|
|
||||||
member = config.hardware.networkInterfaces.wlan1;
|
|
||||||
# Bridge only once hostapd is ready.
|
|
||||||
dependencies = [ config.services.hostap-2-ready ];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bridge = svc.bridge.members.build {
|
||||||
|
primary = config.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 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
admin-vlan = svc.vlan.build {
|
||||||
|
ifname = "admin";
|
||||||
|
primary = config.services.int;
|
||||||
|
vid = "3001";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Default VLAN
|
|
||||||
# services.vlan-apro = svc.vlan.build {
|
|
||||||
# vlanId = 0;
|
|
||||||
# interface = config.services.int;
|
|
||||||
# };
|
|
||||||
|
|
||||||
# # Administration VLAN
|
|
||||||
# services.vlan-admin = svc.vlan.build {
|
|
||||||
# vlan = 3001;
|
|
||||||
# interface = config.services.int;
|
|
||||||
# };
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
svc = config.system.service;
|
svc = config.system.service;
|
||||||
|
parentConfig = config;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
defaultProfile.packages = with pkgs; [
|
defaultProfile.packages = [
|
||||||
# Levitate enable us to mass-reinstall the system on the fly.
|
# Levitate enable us to mass-reinstall the system on the fly.
|
||||||
(levitate.override {
|
(pkgs.levitate.override {
|
||||||
config = {
|
config = {
|
||||||
imports = [
|
imports = [
|
||||||
"${modulesPath}/network"
|
"${modulesPath}/network"
|
||||||
|
@ -19,24 +20,33 @@ in
|
||||||
"${modulesPath}/kernel"
|
"${modulesPath}/kernel"
|
||||||
"${modulesPath}/outputs/tftpboot.nix"
|
"${modulesPath}/outputs/tftpboot.nix"
|
||||||
"${modulesPath}/outputs.nix"
|
"${modulesPath}/outputs.nix"
|
||||||
|
(
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
services = {
|
||||||
|
# In this situation, we fallback to the appro VLAN.
|
||||||
|
# TODO: add support for the admin VLAN.
|
||||||
|
# Simplest DHCPv4 we can find.
|
||||||
|
dhcpv4 = svc.network.dhcp.client.build {
|
||||||
|
interface = parentConfig.hardware.networkInterfaces.lan;
|
||||||
|
};
|
||||||
|
inherit (parentConfig.services) sshd;
|
||||||
|
defaultroute4 = svc.network.route.build {
|
||||||
|
via = "$(output ${config.services.dhcpv4} router)";
|
||||||
|
target = "default";
|
||||||
|
dependencies = [ config.services.dhcpv4 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
hostname = "${parentConfig.hostname}-live";
|
||||||
nixpkgs.buildPlatform = builtins.currentSystem;
|
nixpkgs.buildPlatform = builtins.currentSystem;
|
||||||
services = {
|
|
||||||
# In this situation, we fallback to the appro VLAN.
|
|
||||||
# TODO: add support for the admin VLAN.
|
|
||||||
# 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 ${config.services.dhcpv4} router)";
|
|
||||||
target = "default";
|
|
||||||
dependencies = [ config.services.dhcpv4 ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultProfile.packages = [ mtdutils ];
|
defaultProfile.packages = with pkgs; [
|
||||||
|
mtdutils
|
||||||
|
zyxel-bootconfig
|
||||||
|
];
|
||||||
# Only keep root, which should inherit from DGN access control's root permissions.
|
# Only keep root, which should inherit from DGN access control's root permissions.
|
||||||
users.root = config.users.root;
|
users.root = config.users.root;
|
||||||
};
|
};
|
||||||
|
|
|
@ -131,9 +131,9 @@
|
||||||
"url": "https://git.dgnum.eu/DGNum/liminix"
|
"url": "https://git.dgnum.eu/DGNum/liminix"
|
||||||
},
|
},
|
||||||
"branch": "main",
|
"branch": "main",
|
||||||
"revision": "473d6acc3de70bd6dbbb4a77af54f508f25c3c9c",
|
"revision": "1322de1ee0cdb19fead79e12ab279ee0b575019a",
|
||||||
"url": null,
|
"url": null,
|
||||||
"hash": "00slsh0yqd8n8jcx3sbxgcmw1z28bnszy87pfs0ynfkl3bldzs3d"
|
"hash": "07nk6nik97k8a57cf17dcj3gn2lbhw1myymrxpqc2aqa3haj754k"
|
||||||
},
|
},
|
||||||
"linkal": {
|
"linkal": {
|
||||||
"type": "Git",
|
"type": "Git",
|
||||||
|
|
12
scripts/extract-firmware-from-zyxel-nwa-fit.sh
Executable file
12
scripts/extract-firmware-from-zyxel-nwa-fit.sh
Executable 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
|
53
scripts/liminix-rebuild.sh
Executable file
53
scripts/liminix-rebuild.sh
Executable file
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# TODO: support automatic levitation when the rebuild counts does not fit in the target.
|
||||||
|
# TODO: support preflight checks where we detect the environment we are booted in (this requires the levitation to write a special file).
|
||||||
|
# TODO: use colmena to know the target host and focus on the node name.
|
||||||
|
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
|
||||||
|
;;
|
||||||
|
"--live")
|
||||||
|
echo "Root prefix changed from $root_prefix to /mnt"
|
||||||
|
root_prefix="/mnt"
|
||||||
|
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
|
Loading…
Reference in a new issue