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; + }; + }; +}