9.7 KiB
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:
{
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:
sudo nixos-rebuild switch
Note: For Let'sMesh Analyzer authentication, you need your device's private key. See the 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:
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:
{
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
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:
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:
services.meshcore-packet-capture = {
mqtt1 = {
username = "your_username";
password = "your_password";
};
};
For JWT token authentication:
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
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:
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:
- Bluetooth is enabled:
services.bluetooth.enable = true; - The service user has proper permissions (automatically handled)
- Your Bluetooth adapter is properly configured
Serial port not accessible
Ensure that:
- The device exists:
ls -l /dev/ttyUSB0 - The service user is in the
dialoutgroup (automatically handled) - You've specified the correct port in
serialPorts
Service logs
View service logs with:
journalctl -u meshcore-packet-capture -f
Building the Package
To build just the package (without installing as a service):
nix build
The package will be available at ./result/bin/meshcore-packet-capture.