From 8b3bf8f7e2e88dcf083f02b8ce732a60beb20134 Mon Sep 17 00:00:00 2001 From: agessaman Date: Sun, 9 Nov 2025 19:59:06 -0800 Subject: [PATCH] I think the NixOS flake is okay. If it isn't, send a PR. I gave it my best shot. --- nixos-test/Dockerfile.nix-test | 29 --- nixos-test/NIXOS.md | 362 ------------------------------- nixos-test/README.md | 39 ---- nixos-test/docker-test-simple.sh | 28 --- nixos-test/docker-test.sh | 80 ------- nixos-test/test-nixos-config.nix | 73 ------- 6 files changed, 611 deletions(-) delete mode 100644 nixos-test/Dockerfile.nix-test delete mode 100644 nixos-test/NIXOS.md delete mode 100644 nixos-test/README.md delete mode 100755 nixos-test/docker-test-simple.sh delete mode 100755 nixos-test/docker-test.sh delete mode 100644 nixos-test/test-nixos-config.nix diff --git a/nixos-test/Dockerfile.nix-test b/nixos-test/Dockerfile.nix-test deleted file mode 100644 index 822381f..0000000 --- a/nixos-test/Dockerfile.nix-test +++ /dev/null @@ -1,29 +0,0 @@ -FROM ubuntu:22.04 - -# Install dependencies -RUN apt-get update && apt-get install -y \ - curl \ - git \ - xz-utils \ - sudo \ - && rm -rf /var/lib/apt/lists/* - -# Create nixbld group and user for Nix installation -RUN groupadd -r nixbld && \ - for i in $(seq 1 32); do useradd -r -g nixbld -G nixbld -d /var/empty -s /sbin/nologin -c "Nix build user $i" nixbld$i 2>/dev/null || true; done - -# Install Nix (single-user mode for Docker) -RUN mkdir -m 0755 -p /nix && \ - curl -L https://nixos.org/nix/install | sh -s -- --no-daemon - -# Enable flakes -RUN mkdir -p /root/.config/nix && \ - echo "experimental-features = nix-command flakes" >> /root/.config/nix/nix.conf - -# Set up environment -ENV PATH="/root/.nix-profile/bin:/nix/var/nix/profiles/default/bin:$PATH" - -WORKDIR /workspace - -CMD ["/bin/bash"] - diff --git a/nixos-test/NIXOS.md b/nixos-test/NIXOS.md deleted file mode 100644 index 7c1f755..0000000 --- a/nixos-test/NIXOS.md +++ /dev/null @@ -1,362 +0,0 @@ -# NixOS Support - -This project includes a NixOS service module that allows you to run MeshCore Packet Capture as a systemd service on NixOS. - -## Quick Start - -### Recommended Configuration (Let'sMesh Analyzer) - -This configuration uploads packets to both Let's Mesh Analyzer servers (US and EU) for redundancy, plus an optional third MQTT broker for your own infrastructure: - -Add this to your `/etc/nixos/configuration.nix`: - -```nix -{ - imports = [ - (builtins.fetchTarball "https://github.com/agessaman/meshcore-packet-capture/archive/main.tar.gz") - ]; - - services.meshcore-packet-capture = { - enable = true; - connectionType = "ble"; # or "serial" or "tcp" - - # Connection settings (choose one based on connectionType) - # For BLE: - # bleAddress = "AA:BB:CC:DD:EE:FF"; # optional: specific device address - # bleDeviceName = "MeshCore Device"; # optional: device name to scan for - - # For Serial: - # serialPorts = [ "/dev/ttyUSB0" "/dev/ttyUSB1" ]; # list of ports to try - - # For TCP: - # tcpHost = "localhost"; # TCP server hostname - # tcpPort = 5000; # TCP server port - - # Let'sMesh Analyzer - US Server - mqtt1 = { - enabled = true; - server = "mqtt-us-v1.letsmesh.net"; - port = 443; - transport = "websockets"; - useTLS = true; - useAuthToken = true; - tokenAudience = "mqtt-us-v1.letsmesh.net"; - keepalive = 120; - }; - - # Let'sMesh Analyzer - EU Server - mqtt2 = { - enabled = true; - server = "mqtt-eu-v1.letsmesh.net"; - port = 443; - transport = "websockets"; - useTLS = true; - useAuthToken = true; - tokenAudience = "mqtt-eu-v1.letsmesh.net"; - keepalive = 120; - }; - - # Optional: Your own MQTT broker (uncomment and configure as needed) - # mqtt3 = { - # enabled = true; - # server = "mqtt.example.com"; - # port = 1883; - # username = "your_username"; - # password = "your_password"; - # # or use TLS: - # # port = 8883; - # # useTLS = true; - # }; - - # Device private key for Let'sMesh authentication - # The script automatically fetches the private key from the device if it supports - # ENABLE_PRIVATE_KEY_EXPORT. Only provide these if automatic fetching fails: - # privateKeyFile = "/path/to/your/private/key/file"; - # OR - # privateKey = "your_private_key_hex_string"; - - # Optional: Owner information for Let'sMesh Analyzer - # ownerPublicKey = "YOUR_64_CHAR_HEX_PUBLIC_KEY"; # 64 hex characters - # ownerEmail = "your.email@example.com"; # Email for Let'sMesh Analyzer - - # Optional: IATA code for topic templates - iata = "SEA"; # Replace with your IATA code - }; -} -``` - -Then rebuild your system: - -```bash -sudo nixos-rebuild switch -``` - -**Note:** For Let'sMesh Analyzer authentication, you need your device's private key. See the [Authentication](#authentication) section below for details. - -### Custom MQTT Broker Configuration - -If you prefer to use your own MQTT broker instead of (or in addition to) Let'sMesh Analyzer: - -```nix -services.meshcore-packet-capture = { - enable = true; - connectionType = "ble"; - - mqtt1 = { - enabled = true; - server = "mqtt.example.com"; - port = 1883; # or 8883 for TLS - username = "your_username"; - password = "your_password"; - # Optional: Enable TLS - # useTLS = true; - # tlsVerify = true; - }; -}; -``` - -## Using with Flakes - -If you're using Nix Flakes, add this to your `flake.nix`: - -```nix -{ - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - meshcore-packet-capture = { - url = "github:agessaman/meshcore-packet-capture"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - }; - - outputs = { self, nixpkgs, meshcore-packet-capture }: { - nixosConfigurations.your-hostname = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - meshcore-packet-capture.nixosModules.default - { - services.meshcore-packet-capture = { - enable = true; - package = meshcore-packet-capture.packages.${system}.default; - connectionType = "ble"; - - # Let'sMesh Analyzer - US Server - mqtt1 = { - enabled = true; - server = "mqtt-us-v1.letsmesh.net"; - port = 443; - transport = "websockets"; - useTLS = true; - useAuthToken = true; - tokenAudience = "mqtt-us-v1.letsmesh.net"; - keepalive = 120; - }; - - # Let'sMesh Analyzer - EU Server - mqtt2 = { - enabled = true; - server = "mqtt-eu-v1.letsmesh.net"; - port = 443; - transport = "websockets"; - useTLS = true; - useAuthToken = true; - tokenAudience = "mqtt-eu-v1.letsmesh.net"; - keepalive = 120; - }; - - # Device private key is automatically fetched from the device - # Only set these if automatic fetching fails: - # privateKeyFile = "/path/to/your/private/key/file"; - # privateKey = "your_private_key_hex_string"; - - # Optional: Owner information for Let'sMesh Analyzer - # ownerPublicKey = "YOUR_64_CHAR_HEX_PUBLIC_KEY"; - # ownerEmail = "your.email@example.com"; - - iata = "SEA"; - }; - } - ]; - }; - }; -} -``` - -## Configuration Options - -### Connection Settings - -```nix -services.meshcore-packet-capture = { - connectionType = "ble"; # or "serial" or "tcp" - bleAddress = "AA:BB:CC:DD:EE:FF"; # optional - bleDeviceName = "MeshCore Device"; # optional - serialPorts = [ "/dev/ttyUSB0" "/dev/ttyUSB1" ]; # for serial connection - tcpHost = "localhost"; # for TCP connection - tcpPort = 5000; # for TCP connection - timeout = 30; - maxConnectionRetries = 5; # 0 = infinite - connectionRetryDelay = 5; - healthCheckInterval = 30; -}; -``` - -### MQTT Brokers - -You can configure up to 4 MQTT brokers. Here's an example with Let'sMesh Analyzer (recommended) plus a custom broker: - -```nix -services.meshcore-packet-capture = { - # Let'sMesh Analyzer - US Server - mqtt1 = { - enabled = true; - server = "mqtt-us-v1.letsmesh.net"; - port = 443; - transport = "websockets"; - useTLS = true; - useAuthToken = true; - tokenAudience = "mqtt-us-v1.letsmesh.net"; - keepalive = 120; - }; - - # Let'sMesh Analyzer - EU Server (for redundancy) - mqtt2 = { - enabled = true; - server = "mqtt-eu-v1.letsmesh.net"; - port = 443; - transport = "websockets"; - useTLS = true; - useAuthToken = true; - tokenAudience = "mqtt-eu-v1.letsmesh.net"; - keepalive = 120; - }; - - # Your own MQTT broker (optional) - mqtt3 = { - enabled = true; - server = "mqtt.example.com"; - port = 1883; # or 8883 for TLS - username = "user"; - password = "pass"; - transport = "tcp"; # or "websockets" - useTLS = false; # set to true for TLS - tlsVerify = true; - qos = 0; - retain = false; - keepalive = 60; - # Optional topic overrides - topicStatus = "meshcore/status"; - topicPackets = "meshcore/packets"; - topicRaw = "meshcore/raw"; - }; - - # mqtt4 can be configured similarly -}; -``` - -### Authentication - -For username/password authentication: - -```nix -services.meshcore-packet-capture = { - mqtt1 = { - username = "your_username"; - password = "your_password"; - }; -}; -``` - -For JWT token authentication: - -```nix -services.meshcore-packet-capture = { - mqtt1 = { - useAuthToken = true; - tokenAudience = "mqtt.example.com"; - }; - # Private key is automatically fetched from the device if it supports ENABLE_PRIVATE_KEY_EXPORT - # Only provide these if automatic fetching fails: - # privateKey = "your_private_key_hex_string"; - # OR - # privateKeyFile = "/path/to/private/key/file"; -}; -``` - -### Other Settings - -```nix -services.meshcore-packet-capture = { - logLevel = "INFO"; # DEBUG, INFO, WARNING, ERROR, CRITICAL - verbose = false; - debug = false; - enableMqtt = true; - maxMqttRetries = 5; # 0 = infinite - mqttRetryDelay = 5; - exitOnReconnectFail = true; - iata = "SEA"; # For topic templates - origin = "My Device"; - advertIntervalHours = 11; # 0 = disabled - uploadPacketTypes = [ 0 1 2 ]; # Filter packet types, null = all - rfDataTimeout = 15.0; - outputFile = null; # Optional output file path - # privateKeyFile = "/path/to/private/key/file"; # Only if auto-fetch fails - # privateKey = "hex_string"; # Only if auto-fetch fails - ownerPublicKey = null; # Optional: 64 hex character owner public key - ownerEmail = null; # Optional: Owner email for Let'sMesh Analyzer - dataDir = "/var/lib/meshcore-packet-capture"; - user = "meshcore"; - group = "meshcore"; -}; -``` - -## Permissions - -The service automatically adds the service user to the `bluetooth` and `dialout` groups for BLE and serial port access. - -## Development - -To enter a development shell with all dependencies: - -```bash -nix develop -``` - -## Troubleshooting - -### Package not found - -If you get an error about `meshcore` package not being found, you may need to update the hash in `nix/packages.nix`. The first time you build, Nix will tell you the correct hash to use. - -### BLE not working - -Ensure that: -1. Bluetooth is enabled: `services.bluetooth.enable = true;` -2. The service user has proper permissions (automatically handled) -3. Your Bluetooth adapter is properly configured - -### Serial port not accessible - -Ensure that: -1. The device exists: `ls -l /dev/ttyUSB0` -2. The service user is in the `dialout` group (automatically handled) -3. You've specified the correct port in `serialPorts` - -### Service logs - -View service logs with: - -```bash -journalctl -u meshcore-packet-capture -f -``` - -## Building the Package - -To build just the package (without installing as a service): - -```bash -nix build -``` - -The package will be available at `./result/bin/meshcore-packet-capture`. - diff --git a/nixos-test/README.md b/nixos-test/README.md deleted file mode 100644 index ed65dea..0000000 --- a/nixos-test/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# NixOS Testing - -This directory contains testing scripts and documentation for the NixOS service module. - -## Files - -- **`NIXOS.md`** - Complete documentation for using the NixOS service module -- **`test-nixos-config.nix`** - Example NixOS configuration for testing (use with `nixos-shell` from repository root) -- **`Dockerfile.nix-test`** - Docker image with Nix installed for testing without NixOS -- **`docker-test-simple.sh`** - Quick script to get an interactive Docker shell with Nix -- **`docker-test.sh`** - Automated test script that runs various Nix flake tests - -## Quick Start - -### Testing in Docker (No NixOS Required) - -Get an interactive shell: -```bash -cd nixos-test -./docker-test-simple.sh -``` - -Run automated tests: -```bash -cd nixos-test -./docker-test.sh -``` - -### Testing with nixos-shell (Requires Nix installed) - -From the repository root: -```bash -nixos-shell nixos-test/test-nixos-config.nix -``` - -## Documentation - -See `NIXOS.md` for complete usage instructions and configuration options. - diff --git a/nixos-test/docker-test-simple.sh b/nixos-test/docker-test-simple.sh deleted file mode 100755 index c9c640f..0000000 --- a/nixos-test/docker-test-simple.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# Simple script to get an interactive Docker shell with Nix - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -cd "$REPO_ROOT" - -IMAGE_NAME="meshcore-packet-capture-nix-test" - -# Build the Docker image if it doesn't exist -if ! docker image inspect "$IMAGE_NAME" &>/dev/null; then - echo "Building Docker image..." - docker build -f "$SCRIPT_DIR/Dockerfile.nix-test" -t "$IMAGE_NAME" "$REPO_ROOT" -fi - -# Run interactive container -echo "Starting interactive container..." -echo "The repository is mounted at /workspace" -echo "Nix is installed and flakes are enabled" -echo "" -docker run -it --rm \ - -v "$REPO_ROOT:/workspace" \ - -w /workspace \ - "$IMAGE_NAME" \ - /bin/bash -c "source /root/.nix-profile/etc/profile.d/nix.sh && /bin/bash" - diff --git a/nixos-test/docker-test.sh b/nixos-test/docker-test.sh deleted file mode 100755 index adf401c..0000000 --- a/nixos-test/docker-test.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash -# Script to test the Nix flake in Docker - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -cd "$REPO_ROOT" - -IMAGE_NAME="meshcore-packet-capture-nix-test" -CONTAINER_NAME="meshcore-packet-capture-test" - -# Build the Docker image -echo "Building Docker image..." -docker build -f "$SCRIPT_DIR/Dockerfile.nix-test" -t "$IMAGE_NAME" "$REPO_ROOT" - -# Run the container with the repository mounted -echo "Starting container..." -docker run -it --rm \ - --name "$CONTAINER_NAME" \ - -v "$REPO_ROOT:/workspace" \ - -w /workspace \ - "$IMAGE_NAME" \ - /bin/bash -c " - source /root/.nix-profile/etc/profile.d/nix.sh - - echo '=== Testing flake structure ===' - nix flake show || true - - echo '' - echo '=== Testing package build ===' - nix build .#packages.x86_64-linux.default --no-link || true - - echo '' - echo '=== Testing module syntax ===' - nix-instantiate --eval -E ' - let - pkgs = import {}; - lib = pkgs.lib; - flakeModule = import ./nix/nixos-module.nix { flake-parts-lib = {}; }; - nixosModule = flakeModule.flake.nixosModules.default; - in - lib.isFunction nixosModule - ' --strict || true - - echo '' - echo '=== Testing module with minimal config ===' - nix-instantiate --eval -E ' - let - pkgs = import {}; - lib = pkgs.lib; - flakeModule = import ./nix/nixos-module.nix { flake-parts-lib = {}; }; - nixosModule = flakeModule.flake.nixosModules.default; - eval = import { - modules = [ - nixosModule - { - services.meshcore-packet-capture = { - enable = true; - connectionType = \"ble\"; - mqtt1 = { - enabled = true; - server = \"localhost\"; - port = 1883; - }; - package = pkgs.hello; # Use a dummy package for testing - }; - } - ]; - }; - in - eval.config.services.meshcore-packet-capture.enable - ' --strict || true - - echo '' - echo '=== Interactive shell available ===' - echo 'Run: docker exec -it $CONTAINER_NAME /bin/bash' - /bin/bash - " - diff --git a/nixos-test/test-nixos-config.nix b/nixos-test/test-nixos-config.nix deleted file mode 100644 index a78b8f4..0000000 --- a/nixos-test/test-nixos-config.nix +++ /dev/null @@ -1,73 +0,0 @@ -{ config, pkgs, ... }: -let - # Get the package from the flake using builtins.getFlake - # This requires the flake to be accessible (either in registry or as a path) - # Note: This file should be run from the repository root, or paths adjusted accordingly - repoRoot = toString ../.; - flake = builtins.getFlake repoRoot; - # Get the package for the current system - system = pkgs.system; - meshcorePackage = flake.packages.${system}.default; - - # Import the flake module and extract the NixOS module - flakeModule = import ../nix/nixos-module.nix { flake-parts-lib = {}; }; - meshcoreModule = flakeModule.flake.nixosModules.default; -in -{ - imports = [ - meshcoreModule - ]; - - # Set system state version to avoid warnings - system.stateVersion = "24.11"; - - services.meshcore-packet-capture = { - enable = true; - - # Override the package to use the flake's package - package = meshcorePackage; - - connectionType = "ble"; - bleDeviceName = "MeshCore-HOWL Ikoka"; # Specific device to connect to - # OR use bleAddress = "AA:BB:CC:DD:EE:FF"; for a specific address - - # Let'sMesh Analyzer - US Server - mqtt1 = { - enabled = true; - server = "mqtt-us-v1.letsmesh.net"; - port = 443; - transport = "websockets"; - useTLS = true; - useAuthToken = true; - tokenAudience = "mqtt-us-v1.letsmesh.net"; - keepalive = 120; - }; - - # Let'sMesh Analyzer - EU Server - mqtt2 = { - enabled = true; - server = "mqtt-eu-v1.letsmesh.net"; - port = 443; - transport = "websockets"; - useTLS = true; - useAuthToken = true; - tokenAudience = "mqtt-eu-v1.letsmesh.net"; - keepalive = 120; - }; - - # Device private key for Let'sMesh authentication - # The script will automatically fetch the private key from the device if it supports - # ENABLE_PRIVATE_KEY_EXPORT. Only provide these if automatic fetching fails: - # privateKeyFile = "/path/to/your/private/key/file"; - # OR - # privateKey = "your_private_key_hex_string"; - - # Optional: Owner information for Let'sMesh Analyzer - # ownerPublicKey = "dadadadaa3965eb49a7aa8158bd4a4f3a73f711585f8dcffb13a7497e071ddda"; - # ownerEmail = "adam@gessaman.com"; - - # IATA code for topic templates - iata = "SEA"; # Replace with your IATA code - }; -} -