From db2bd1d15727cc283cad6097cd742fd4a6c92f06 Mon Sep 17 00:00:00 2001 From: Hermes Date: Wed, 20 May 2026 14:34:15 -0400 Subject: [PATCH 01/10] feat: add uConsole CM5 host configuration with Reticulum mesh stack - New NixOS host 'uConsole' for ClockworkPi CM5 portable terminal - flake.nix: add nixos-uconsole and nixos-raspberrypi inputs - Imports: nixos-uconsole.nixosModules.uconsole-cm5, nixos-raspberrypi.nixosModules.raspberry-pi-5.base - Full package list: base tools, HAM radio, SDR/RF, mesh/LoRa, security tools, GPS/maps - Reticulum stack (rns 1.2.9, lxmf 0.9.8, nomadnet 1.1.1) built from PyPI via overlays/reticulum.nix - systemd services: rnsd (Reticulum daemon), kismet (Wi-Fi IDS) - Kernel modules for SDR (rtl-sdr, dvb) and USB WiFi - Follows existing host config conventions (cyt-pi as template) --- flake.nix | 28 +++- hosts/uConsole/configuration.nix | 167 ++++++++++++++++++++++ hosts/uConsole/hardware-configuration.nix | 26 ++++ overlays/reticulum.nix | 77 ++++++++++ 4 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 hosts/uConsole/configuration.nix create mode 100644 hosts/uConsole/hardware-configuration.nix create mode 100644 overlays/reticulum.nix diff --git a/flake.nix b/flake.nix index 8f8b51a..8f51b77 100644 --- a/flake.nix +++ b/flake.nix @@ -12,10 +12,18 @@ url = "git+https://git.lix.systems/lix-project/lix?ref=main"; inputs.nixpkgs.follows = "nixpkgs"; }; + nixos-uconsole = { + url = "github:nixos-uconsole/nixos-uconsole"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nixos-raspberrypi = { + url = "github:nvmd/nixos-raspberrypi/v1.20260317.0"; + inputs.nixpkgs.follows = "nixpkgs"; + }; self.submodules = true; }; - outputs = { self, nixpkgs, agenix, lix, ... }@inputs: + outputs = { self, nixpkgs, agenix, lix, nixos-uconsole, nixos-raspberrypi, ... }@inputs: let system = "x86_64-linux"; keys = import ./lib/keys.nix; @@ -26,7 +34,7 @@ "/etc/ssh/ssh_host_ed25519_key" "/root/.age/bootstrap.key" ]; }; - overlays = [ agenix.overlays.default ]; + overlays = [ agenix.overlays.default (import ./overlays/reticulum.nix) ]; pkgs = import nixpkgs { inherit system overlays; config.allowUnfree = true; @@ -80,6 +88,22 @@ ./hosts/cyt-pi/hardware-configuration.nix ]; }; + + uConsole = nixos-raspberrypi.lib.nixosSystem { + specialArgs = { inherit self keys paths inputs nixos-raspberrypi; }; + modules = [ + { + nixpkgs.overlays = overlays; + nixpkgs.config.allowUnfree = true; + nixpkgs.hostPlatform = "aarch64-linux"; + nix.package = lix.packages."aarch64-linux".default; + } + nixos-raspberrypi.nixosModules.raspberry-pi-5.base + nixos-uconsole.nixosModules.uconsole-cm5 + ./hosts/uConsole/configuration.nix + ./hosts/uConsole/hardware-configuration.nix + ]; + }; }; devShells.${system}.default = devShell; }; diff --git a/hosts/uConsole/configuration.nix b/hosts/uConsole/configuration.nix new file mode 100644 index 0000000..73a59b1 --- /dev/null +++ b/hosts/uConsole/configuration.nix @@ -0,0 +1,167 @@ +{ config, lib, pkgs, paths, self, ... }: + +{ + # Basic Host Info + networking.hostName = "uConsole"; + time.timeZone = "America/Montreal"; + i18n.defaultLocale = "en_CA.UTF-8"; + + # System State + system.stateVersion = "25.05"; + + # Boot & Hardware (uconsole-cm5 module handles boot.loader) + boot.kernelPackages = pkgs.linuxPackages_latest; + + # Networking + networking.networkmanager.enable = true; + services.openssh = { + enable = true; + settings.PermitRootLogin = "prohibit-password"; + settings.PasswordAuthentication = false; + }; + + # User + users.users.gortium = { + isNormalUser = true; + extraGroups = [ "wheel" "networkmanager" "video" "dialout" "kismet" ]; + openssh.authorizedKeys.keys = [ + keys.users.gortium.main + keys.users.gortium.gitea + ]; + }; + security.sudo.extraRules = [ + { + users = [ "gortium" ]; + commands = [ + { + command = "ALL"; + options = [ "NOPASSWD" ]; + } + ]; + } + ]; + + # ============================================================ + # Package groups + # ============================================================ + + environment.systemPackages = with pkgs; [ + # ===== Base ===== + emacs-pgtk + git + ripgrep + fd + htop + tmux + neovim + + # ===== HAM Radio ===== + js8call + wsjtx + fldigi + pat # Winlink client + direwolf # AX.25 packet modem + chirp # Radio programming tool + hamlib # Ham radio control libraries + trustedqsl # Logbook of the World (LoTW) + + # ===== SDR / RF ===== + sdrpp # SDR++ spectrum analyzer + gqrx # SDR receiver GUI + rtl-sdr # RTL-SDR drivers & utilities + inspectrum # Offline signal analysis + soapysdr-with-plugins # SoapySDR + hardware support plugins + + # ===== Mesh / LoRa ===== + meshtastic # Python CLI for Meshtastic devices + reticulumStack # Reticulum Network Stack (rnsd, rnsh, rncp, rnx, rnpath, etc.) + lxmf # LXMF messaging protocol + nomadnet # Nomad Network client + + # ===== Security ===== + nmap + aircrack-ng + kismet # Wi-Fi monitor / IDS + bettercap # MITM/network attack framework + wireshark # Packet analyzer + hashcat # GPU password cracker + john # John the Ripper + sqlmap # SQL injection tool + + # ===== GPS / Maps ===== + foxtrotgps + viking # GPS map editor + gpsbabel # GPS data conversion + ]; + + # Packages noted but not in unstable nixpkgs: + # - metasploit: unfree; install manually via Git clone + # - burpsuite: unfree Java app (Community Edition available for download) + # - sidechannel: not a distinct PyPI package; functionality covered by + # the Reticulum stack. For LXMF GUI client, install Sideband manually + # from github.com/markqvist/Sideband + + # ============================================================ + # Reticulum Service (rnsd) + # ============================================================ + systemd.services.rnsd = { + description = "Reticulum Network Stack Daemon"; + after = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = "gortium"; + Group = "gortium"; + ExecStart = "${pkgs.reticulumStack}/bin/rnsd"; + Restart = "always"; + RestartSec = "10s"; + LimitNOFILE = 65536; + }; + }; + + # ============================================================ + # Kismet Service (Wi-Fi monitoring / mesh node) + # ============================================================ + systemd.services.kismet = { + description = "Kismet Wi-Fi Monitor & IDS"; + after = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = "gortium"; + Group = "kismet"; + ExecStart = "${pkgs.kismet}/bin/kismet -c wlan0 --log-base=/home/gortium/kismet_logs --no-nc-ui"; + Restart = "always"; + RestartSec = "10s"; + }; + }; + + # ============================================================ + # Kernel modules for SDR and radio + # ============================================================ + boot.kernelModules = [ + "88x2bu" # Realtek 8812/8821BU USB WiFi (common adapter) + "rtl8xxxu" # RTL8188/8192/8723 USB WiFi + "rtl2832_sdr" # RTL-SDR kernel module + "dvb_usb_rtl28xxu" # RTL-SDR DVB-T + ]; + + boot.blacklistedKernelModules = [ ]; + + # ============================================================ + # Extra udev rules for SDR and HAM radio devices + # ============================================================ + services.udev.packages = with pkgs; [ rtl-sdr ]; + + # ============================================================ + # Enable IPv6 for Reticulum mesh + # ============================================================ + networking.enableIPv6 = true; + + # ============================================================ + # Firewall: open ports for Reticulum (optional) + # ============================================================ + networking.firewall.allowedTCPPorts = [ 22 ]; # SSH only + networking.firewall.allowedUDPPorts = [ ]; + # Reticulum uses its own encryption and doesn't need open ports + # for basic mesh operations (peer-to-peer discovery). + # For TCP interfaces, open additional ports as needed. +} diff --git a/hosts/uConsole/hardware-configuration.nix b/hosts/uConsole/hardware-configuration.nix new file mode 100644 index 0000000..ea7c25a --- /dev/null +++ b/hosts/uConsole/hardware-configuration.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "usbhid" "usb_storage" "sdhci_pci" "nvme" ]; + boot.initrd.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + # uConsole CM5 uses NVMe or eMMC for boot storage + # The uconsole-cm5 module sets up /boot/firmware and default / + # Override device label here if using different storage + fileSystems."/" = lib.mkDefault { + device = "/dev/disk/by-label/NIXOS_UCM5"; + fsType = "ext4"; + options = [ "noatime" ]; + }; + + swapDevices = [ ]; + + nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; + hardware.enableRedistributableFirmware = true; + powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; +} diff --git a/overlays/reticulum.nix b/overlays/reticulum.nix new file mode 100644 index 0000000..ffab686 --- /dev/null +++ b/overlays/reticulum.nix @@ -0,0 +1,77 @@ +final: prev: let + python3 = final.python3; + pyPkgs = python3.pkgs; +in { + reticulumStack = python3.pkgs.buildPythonApplication rec { + pname = "reticulum"; + version = "1.2.9"; + src = pyPkgs.fetchPypi { + pname = "rns"; + inherit version; + sha256 = "554814231c237b9caacf8df669312e57dd7d3f84b6d4810125087d1a79a75d75"; + }; + propagatedBuildInputs = with pyPkgs; [ cryptography pyserial ]; + doCheck = false; + pythonImportsCheck = [ "RNS" ]; + meta = with final.lib; { + description = "Self-configuring, encrypted and resilient mesh networking stack"; + homepage = "https://reticulum.network/"; + license = licenses.mit; + platforms = platforms.linux; + }; + }; + + lxmf = python3.pkgs.buildPythonApplication rec { + pname = "lxmf"; + version = "0.9.8"; + src = pyPkgs.fetchPypi { + inherit pname version; + sha256 = "30f39f3a975a049c12ee2cfceb3261d24cb5adec881c6821f7354464b3f3650c"; + }; + propagatedBuildInputs = [ final.reticulumStack ]; + doCheck = false; + pythonImportsCheck = [ "LXMF" ]; + meta = with final.lib; { + description = "Lightweight Extensible Message Format for Reticulum"; + homepage = "https://github.com/markqvist/lxmf"; + license = licenses.mit; + platforms = platforms.linux; + }; + }; + + nomadnet = python3.pkgs.buildPythonApplication rec { + pname = "nomadnet"; + version = "1.1.1"; + src = pyPkgs.fetchPypi { + inherit pname version; + sha256 = "fa13b64a10e75b705a58024815ab72451700aa726af96d415ba99dec28dfc40a"; + }; + propagatedBuildInputs = with pyPkgs; [ final.reticulumStack final.lxmf urwid qrcode ]; + doCheck = false; + pythonImportsCheck = [ "nomadnet" ]; + meta = with final.lib; { + description = "Nomad Network — resilient mesh communications platform"; + homepage = "https://github.com/markqvist/NomadNet"; + license = licenses.mit; + platforms = platforms.linux; + }; + }; + + rnsh = python3.pkgs.buildPythonApplication rec { + pname = "rnsh"; + version = "0.1.7"; + src = pyPkgs.fetchPypi { + inherit pname version; + sha256 = "9cb72f25abb1c6d300f8014b264184ff78f592fe88e36094938012990b797c93"; + }; + propagatedBuildInputs = [ final.reticulumStack ]; + doCheck = false; + pythonImportsCheck = [ "rnsh" ]; + meta = with final.lib; { + description = "Remote shell over Reticulum"; + homepage = "https://github.com/acehoss/rnsh"; + license = licenses.mit; + platforms = platforms.linux; + }; + }; +} From b66ffadb79c057cc3ede0ddca311368598905726 Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 5 Jun 2026 22:43:53 -0400 Subject: [PATCH 02/10] fix: add missing 'keys' to uConsole module args --- hosts/uConsole/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/uConsole/configuration.nix b/hosts/uConsole/configuration.nix index 73a59b1..aeebcb8 100644 --- a/hosts/uConsole/configuration.nix +++ b/hosts/uConsole/configuration.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, paths, self, ... }: +{ config, lib, pkgs, paths, self, keys, ... }: { # Basic Host Info From a0a6663793a9539dd61f7273e25ce894a9d49a63 Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 5 Jun 2026 22:45:30 -0400 Subject: [PATCH 03/10] fix: use mkForce for PasswordAuthentication to override upstream module default --- hosts/uConsole/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/uConsole/configuration.nix b/hosts/uConsole/configuration.nix index aeebcb8..dbd71e3 100644 --- a/hosts/uConsole/configuration.nix +++ b/hosts/uConsole/configuration.nix @@ -17,7 +17,7 @@ services.openssh = { enable = true; settings.PermitRootLogin = "prohibit-password"; - settings.PasswordAuthentication = false; + settings.PasswordAuthentication = lib.mkForce false; }; # User From bdd6d0373960dffdf16240d6639084e21b6a9c70 Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 5 Jun 2026 22:45:59 -0400 Subject: [PATCH 04/10] fix: use mkForce for PermitRootLogin to override upstream module default --- hosts/uConsole/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/uConsole/configuration.nix b/hosts/uConsole/configuration.nix index dbd71e3..c0a83fb 100644 --- a/hosts/uConsole/configuration.nix +++ b/hosts/uConsole/configuration.nix @@ -16,7 +16,7 @@ networking.networkmanager.enable = true; services.openssh = { enable = true; - settings.PermitRootLogin = "prohibit-password"; + settings.PermitRootLogin = lib.mkForce "prohibit-password"; settings.PasswordAuthentication = lib.mkForce false; }; From 24f15c98cd5646b3fd1378d98c4046a51fd7b0d6 Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 5 Jun 2026 22:46:54 -0400 Subject: [PATCH 05/10] fix: add format=setuptools to all reticulum overlay python packages --- overlays/reticulum.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/overlays/reticulum.nix b/overlays/reticulum.nix index ffab686..e646559 100644 --- a/overlays/reticulum.nix +++ b/overlays/reticulum.nix @@ -5,6 +5,7 @@ in { reticulumStack = python3.pkgs.buildPythonApplication rec { pname = "reticulum"; version = "1.2.9"; + format = "setuptools"; src = pyPkgs.fetchPypi { pname = "rns"; inherit version; @@ -24,6 +25,7 @@ in { lxmf = python3.pkgs.buildPythonApplication rec { pname = "lxmf"; version = "0.9.8"; + format = "setuptools"; src = pyPkgs.fetchPypi { inherit pname version; sha256 = "30f39f3a975a049c12ee2cfceb3261d24cb5adec881c6821f7354464b3f3650c"; @@ -42,6 +44,7 @@ in { nomadnet = python3.pkgs.buildPythonApplication rec { pname = "nomadnet"; version = "1.1.1"; + format = "setuptools"; src = pyPkgs.fetchPypi { inherit pname version; sha256 = "fa13b64a10e75b705a58024815ab72451700aa726af96d415ba99dec28dfc40a"; @@ -60,6 +63,7 @@ in { rnsh = python3.pkgs.buildPythonApplication rec { pname = "rnsh"; version = "0.1.7"; + format = "setuptools"; src = pyPkgs.fetchPypi { inherit pname version; sha256 = "9cb72f25abb1c6d300f8014b264184ff78f592fe88e36094938012990b797c93"; From 1617ac9149d211fbfcb1db72d85c62341cdc7833 Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 5 Jun 2026 22:57:26 -0400 Subject: [PATCH 06/10] fix: migrate from deprecated kernelboot to kernel bootloader for nixos-raspberrypi --- hosts/uConsole/configuration.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hosts/uConsole/configuration.nix b/hosts/uConsole/configuration.nix index c0a83fb..8a550e8 100644 --- a/hosts/uConsole/configuration.nix +++ b/hosts/uConsole/configuration.nix @@ -9,7 +9,8 @@ # System State system.stateVersion = "25.05"; - # Boot & Hardware (uconsole-cm5 module handles boot.loader) + # Boot & Hardware (migrated to kernel bootloader per nixos-raspberrypi deprecation notice) + boot.loader.raspberry-pi.bootloader = "kernel"; boot.kernelPackages = pkgs.linuxPackages_latest; # Networking From 29cc20bb041a38a6a362e0580cc52aae98e54e9e Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 5 Jun 2026 22:58:09 -0400 Subject: [PATCH 07/10] fix: add wants=network-online.target to rnsd and kismet services to silence eval warnings --- hosts/uConsole/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hosts/uConsole/configuration.nix b/hosts/uConsole/configuration.nix index 8a550e8..ef1b9dc 100644 --- a/hosts/uConsole/configuration.nix +++ b/hosts/uConsole/configuration.nix @@ -107,6 +107,7 @@ # ============================================================ systemd.services.rnsd = { description = "Reticulum Network Stack Daemon"; + wants = [ "network-online.target" ]; after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { @@ -124,6 +125,7 @@ # ============================================================ systemd.services.kismet = { description = "Kismet Wi-Fi Monitor & IDS"; + wants = [ "network-online.target" ]; after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { From 7f11da1878681ef138bb0b31fd5945a392dbeb1b Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 5 Jun 2026 23:33:10 -0400 Subject: [PATCH 08/10] fix: let nixos-raspberrypi manage kernel version (patches incompatible with linuxPackages_latest) --- hosts/uConsole/configuration.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hosts/uConsole/configuration.nix b/hosts/uConsole/configuration.nix index ef1b9dc..26e0d72 100644 --- a/hosts/uConsole/configuration.nix +++ b/hosts/uConsole/configuration.nix @@ -11,7 +11,8 @@ # Boot & Hardware (migrated to kernel bootloader per nixos-raspberrypi deprecation notice) boot.loader.raspberry-pi.bootloader = "kernel"; - boot.kernelPackages = pkgs.linuxPackages_latest; + # kernel managed by nixos-raspberrypi module — don't override, patches are version-specific + # boot.kernelPackages = pkgs.linuxPackages_latest; # Networking networking.networkmanager.enable = true; From 9ebbb1c0c6d2b37a89d02c1f1344a3101a6719dc Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 5 Jun 2026 23:38:21 -0400 Subject: [PATCH 09/10] fix: bump nixos-raspberrypi to v1.20260517.0 (matches nixos-uconsole tested version) --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 8f51b77..ea2a6b6 100644 --- a/flake.nix +++ b/flake.nix @@ -17,7 +17,7 @@ inputs.nixpkgs.follows = "nixpkgs"; }; nixos-raspberrypi = { - url = "github:nvmd/nixos-raspberrypi/v1.20260317.0"; + url = "github:nvmd/nixos-raspberrypi/v1.20260517.0"; inputs.nixpkgs.follows = "nixpkgs"; }; self.submodules = true; From a51e09571725594f9e6fb629f646498efad64ea4 Mon Sep 17 00:00:00 2001 From: Hermes Date: Sat, 6 Jun 2026 09:16:23 -0400 Subject: [PATCH 10/10] feat: enable aarch64 cross-build on lazyworkhorse (QEMU binfmt + extra-platforms) --- hosts/lazyworkhorse/configuration.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hosts/lazyworkhorse/configuration.nix b/hosts/lazyworkhorse/configuration.nix index f1afae4..6f02a2b 100644 --- a/hosts/lazyworkhorse/configuration.nix +++ b/hosts/lazyworkhorse/configuration.nix @@ -11,6 +11,10 @@ # Flakesss nix.settings.experimental-features = [ "nix-command" "flakes" "flake-self-attrs" ]; nix.settings.trusted-users = [ "root" "gortium" ]; + nix.settings.extra-platforms = [ "aarch64-linux" ]; + + # QEMU binfmt for cross-building aarch64 NixOS targets + boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; # Garbage collection nix.gc = {