{ config, lib, pkgs, paths, self, keys, ... }: let # Backlight fallback for CM5 display quirk # The kernel driver usually handles this, but some boots need a kick backlightFixScript = pkgs.writeShellScript "backlight-fix" '' # Try sysfs backlight control for bl in /sys/class/backlight/*/brightness; do if [ -f "$bl" ]; then max=$(cat "$(dirname "$bl")/max_brightness" 2>/dev/null || echo 100) echo "$max" > "$bl" 2>/dev/null || true fi done ''; in { # Basic Host Info networking.hostName = "uConsole"; time.timeZone = "America/Montreal"; i18n.defaultLocale = "en_CA.UTF-8"; # System State system.stateVersion = "25.05"; # Boot & Hardware (migrated to kernel bootloader per nixos-raspberrypi deprecation notice) boot.loader.raspberry-pi.bootloader = "kernel"; # kernel managed by nixos-raspberrypi module — don't override, patches are version-specific # boot.kernelPackages = pkgs.linuxPackages_latest; # Networking networking.networkmanager.enable = true; services.openssh = { enable = true; settings.PermitRootLogin = lib.mkForce "prohibit-password"; settings.PasswordAuthentication = lib.mkForce 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 libgpiod # GPIO control (for internal USB hub, AIO modules) # ===== 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"; wants = [ "network-online.target" ]; 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"; wants = [ "network-online.target" ]; 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, radio, and WiFi # ============================================================ boot.kernelModules = [ "mt7921u" # MediaTek MT7921 USB WiFi (uConsole AC1200) "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. # ============================================================ # Display & Desktop (Hyprland Wayland compositor) # ============================================================ programs.hyprland = { enable = true; xwayland.enable = true; }; services.displayManager.sddm = { enable = true; wayland.enable = true; }; # ============================================================ # CM5 Display Backlight Fix # The kernel driver initializes backlight, but some boots fail. # This service kicks it after boot as a reliable fallback. # ============================================================ systemd.services.cm5-backlight-fix = { description = "CM5 Display Backlight Fix"; after = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; ExecStart = "${backlightFixScript}"; }; }; # ============================================================ # Internal USB Hub Enable (GPIO 23) # The Hacker Gadgets AIO V2 board has an internal USB hub for # the AC1200 WiFi, SDR, and other peripherals. GPIO 23 must be # HIGH to power the hub. CM5 defaults GPIO 23 to LOW. # ============================================================ systemd.services.enable-gpio23-usb-hub = { description = "Enable Internal USB Hub (GPIO 23)"; before = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; ExecStart = "${pkgs.libgpiod}/bin/gpioset 0 23=1"; ExecStop = "${pkgs.libgpiod}/bin/gpioset 0 23=0"; }; }; }