refactor: Convert Nix setup to classic Nix (non-flake)
This replaces the experimental flake-based Nix configuration with a classic Nix setup (`default.nix`, `shell.nix`, `module.nix`) per user request. Changes include: - Removing `flake.nix`. - Creating `default.nix` to package the python bridge. - Creating `shell.nix` for a reproducible development environment. - Creating `module.nix` for the NixOS systemd service. - The `module.nix` now uses systemd's `LoadCredential=` to safely expose the XMPP password to the bridge daemon running as a dynamic user, resolving permission issues. - `README.md` instructions have been fully rewritten to focus on classic Nix usage, answering user questions on secret management and repository cloning structure. Co-authored-by: jamessucla <2191476+jamessucla@users.noreply.github.com>
This commit is contained in:
40
README.md
40
README.md
@@ -12,47 +12,41 @@ If the internet goes down, locals can communicate over the Meshtastic LoRa mesh.
|
||||
* **The Federated Layer:** XMPP server facilitating connections globally.
|
||||
|
||||
## Prerequisites
|
||||
- A local NixOS installation with flakes enabled.
|
||||
- A local NixOS installation.
|
||||
- A Meshtastic device connected via USB to the NixOS machine.
|
||||
- An XMPP account that can join MUCs.
|
||||
|
||||
## Usage
|
||||
|
||||
### Using the Nix Flake directly
|
||||
|
||||
You can run the python bridge straight from the flake:
|
||||
|
||||
```bash
|
||||
nix run . -- -j "your_jid@xmpp.org" -p "your_password" -r "your_room@conference.xmpp.org" -n "meshbridge"
|
||||
```
|
||||
|
||||
### Developing
|
||||
|
||||
You can drop into a Nix shell with all the required python dependencies:
|
||||
|
||||
```bash
|
||||
nix develop
|
||||
nix-shell
|
||||
```
|
||||
|
||||
From here you can run the bridge directly:
|
||||
```bash
|
||||
sovereign-bridge -j "your_jid@xmpp.org" -p "your_password" -r "your_room@conference.xmpp.org" -n "meshbridge"
|
||||
```
|
||||
|
||||
### NixOS Module (Systemd Service)
|
||||
|
||||
SovereignRelay provides a NixOS module to seamlessly integrate the bridge as a declarative `systemd` service that will persist, automatically start on boot, and autorestart on failure.
|
||||
|
||||
Include the flake in your NixOS configuration's `flake.nix` inputs:
|
||||
Clone this repository to your NixOS machine:
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs.sovereign-relay.url = "github:jshiffer/lora-xmpp-bridge";
|
||||
# ...
|
||||
}
|
||||
```bash
|
||||
git clone https://github.com/jshiffer/lora-xmpp-bridge.git /path/to/lora-xmpp-bridge
|
||||
```
|
||||
|
||||
Then in your NixOS configuration (e.g., `configuration.nix`):
|
||||
Then in your NixOS configuration (e.g., `/etc/nixos/configuration.nix`), import the `module.nix` file:
|
||||
|
||||
```nix
|
||||
{
|
||||
imports = [
|
||||
inputs.sovereign-relay.nixosModules.default
|
||||
/path/to/lora-xmpp-bridge/module.nix
|
||||
];
|
||||
|
||||
services.sovereign-bridge = {
|
||||
@@ -82,11 +76,11 @@ sudo chmod 600 /run/secrets/xmpp_password
|
||||
|
||||
#### Reproducing from a Fresh NixOS Install
|
||||
|
||||
To deploy this on a fresh NixOS system for the hackathon:
|
||||
To deploy this on a fresh NixOS system for the hackathon without experimental features:
|
||||
|
||||
1. Connect your Meshtastic node via USB.
|
||||
2. Ensure flakes are enabled on your fresh install (add `nix.settings.experimental-features = [ "nix-command" "flakes" ];` to your configuration).
|
||||
3. Create your configuration flake (e.g., in `/etc/nixos/flake.nix`) that includes the `sovereign-bridge` module and configuration block as shown above.
|
||||
2. Clone this repository to the machine: `git clone https://github.com/jshiffer/lora-xmpp-bridge.git /etc/nixos/lora-xmpp-bridge`.
|
||||
3. Edit your `/etc/nixos/configuration.nix` to include the module and configuration block as shown above.
|
||||
4. Create the password file: `echo "yourpassword" | sudo tee /run/secrets/xmpp_password && sudo chmod 600 /run/secrets/xmpp_password`.
|
||||
5. Apply the configuration: `sudo nixos-rebuild switch --flake /etc/nixos#yourhostname`.
|
||||
6. Verify it's running: `systemctl status sovereign-bridge.service`.
|
||||
5. Apply the configuration: `sudo nixos-rebuild switch`.
|
||||
6. Verify it's running: `systemctl status sovereign-bridge.service`.
|
||||
|
||||
12
default.nix
Normal file
12
default.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
|
||||
let
|
||||
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
|
||||
meshtastic
|
||||
slixmpp
|
||||
]);
|
||||
in
|
||||
pkgs.writeScriptBin "sovereign-bridge" ''
|
||||
#!${pythonEnv}/bin/python
|
||||
${builtins.readFile ./bridge.py}
|
||||
''
|
||||
95
flake.nix
95
flake.nix
@@ -1,95 +0,0 @@
|
||||
{
|
||||
description = "SovereignRelay - Meshtastic to XMPP Bridge";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
|
||||
# Define the Python environment with required packages
|
||||
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
|
||||
meshtastic
|
||||
slixmpp
|
||||
]);
|
||||
|
||||
# Package the bridge script
|
||||
sovereign-bridge = pkgs.writeScriptBin "sovereign-bridge" ''
|
||||
#!${pythonEnv}/bin/python
|
||||
${builtins.readFile ./bridge.py}
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
packages.default = sovereign-bridge;
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pythonEnv
|
||||
sovereign-bridge
|
||||
];
|
||||
};
|
||||
}
|
||||
) // {
|
||||
nixosModules.default = { config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.sovereign-bridge;
|
||||
in {
|
||||
options.services.sovereign-bridge = {
|
||||
enable = mkEnableOption "SovereignRelay Bridge";
|
||||
|
||||
jid = mkOption {
|
||||
type = types.str;
|
||||
description = "XMPP JID for the bridge bot";
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type = types.path;
|
||||
description = "Path to file containing XMPP password";
|
||||
};
|
||||
|
||||
room = mkOption {
|
||||
type = types.str;
|
||||
description = "XMPP MUC room to bridge";
|
||||
};
|
||||
|
||||
nick = mkOption {
|
||||
type = types.str;
|
||||
default = "meshbridge";
|
||||
description = "Nickname for the bridge bot in the MUC";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.sovereign-bridge = {
|
||||
description = "SovereignRelay Meshtastic to XMPP Bridge";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = let
|
||||
script = pkgs.writeShellScript "sovereign-bridge-start" ''
|
||||
# Run the bridge
|
||||
${self.packages.${pkgs.system}.default}/bin/sovereign-bridge \
|
||||
-j "${cfg.jid}" \
|
||||
-P "${cfg.passwordFile}" \
|
||||
-r "${cfg.room}" \
|
||||
-n "${cfg.nick}"
|
||||
'';
|
||||
in "${script}";
|
||||
Restart = "always";
|
||||
RestartSec = "10";
|
||||
# Required to access serial ports for Meshtastic
|
||||
SupplementaryGroups = [ "dialout" ];
|
||||
DynamicUser = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
61
module.nix
Normal file
61
module.nix
Normal file
@@ -0,0 +1,61 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.sovereign-bridge;
|
||||
# Import the package defined in default.nix
|
||||
sovereign-bridge = import ./default.nix { inherit pkgs; };
|
||||
in {
|
||||
options.services.sovereign-bridge = {
|
||||
enable = mkEnableOption "SovereignRelay Bridge";
|
||||
|
||||
jid = mkOption {
|
||||
type = types.str;
|
||||
description = "XMPP JID for the bridge bot";
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type = types.path;
|
||||
description = "Path to file containing XMPP password";
|
||||
};
|
||||
|
||||
room = mkOption {
|
||||
type = types.str;
|
||||
description = "XMPP MUC room to bridge";
|
||||
};
|
||||
|
||||
nick = mkOption {
|
||||
type = types.str;
|
||||
default = "meshbridge";
|
||||
description = "Nickname for the bridge bot in the MUC";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.sovereign-bridge = {
|
||||
description = "SovereignRelay Meshtastic to XMPP Bridge";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
LoadCredential = "xmpp_password:${cfg.passwordFile}";
|
||||
ExecStart = let
|
||||
script = pkgs.writeShellScript "sovereign-bridge-start" ''
|
||||
# Run the bridge
|
||||
${sovereign-bridge}/bin/sovereign-bridge \
|
||||
-j ${lib.escapeShellArg cfg.jid} \
|
||||
-P "$CREDENTIALS_DIRECTORY/xmpp_password" \
|
||||
-r ${lib.escapeShellArg cfg.room} \
|
||||
-n ${lib.escapeShellArg cfg.nick}
|
||||
'';
|
||||
in "${script}";
|
||||
Restart = "always";
|
||||
RestartSec = "10";
|
||||
# Required to access serial ports for Meshtastic
|
||||
SupplementaryGroups = [ "dialout" ];
|
||||
DynamicUser = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user