meshtasticd: build from source, nixos/meshtastic: init (#466509)
This commit is contained in:
@@ -10,6 +10,10 @@
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- [Meshtastic](https://meshtastic.org), an open-source, off-grid, decentralised mesh network
|
||||
designed to run on affordable, low-power devices. Available as [services.meshtasticd]
|
||||
(#opt-services.meshtasticd.enable).
|
||||
|
||||
- [knot-resolver](https://www.knot-resolver.cz/) in version 6. Available as `services.knot-resolver`. A module for knot-resolver 5 was already available as `services.kresd`.
|
||||
|
||||
- [ImmichFrame](https://immichframe.dev/), display your photos from Immich as a digital photo frame. Available as `services.immichframe`.
|
||||
|
||||
@@ -1248,6 +1248,7 @@
|
||||
./services/networking/lxd-image-server.nix
|
||||
./services/networking/magic-wormhole-mailbox-server.nix
|
||||
./services/networking/matterbridge.nix
|
||||
./services/networking/meshtasticd.nix
|
||||
./services/networking/microsocks.nix
|
||||
./services/networking/mihomo.nix
|
||||
./services/networking/minidlna.nix
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Meshtasticd {#module-services-meshtasticd}
|
||||
|
||||
[Meshtasticd](https://meshtastic.org/) daemon.
|
||||
|
||||
Meshtastic is an open-source, off-grid, decentralised mesh network designed to
|
||||
run on affordable, low-power devices.
|
||||
|
||||
Meshtastic is a project that enables you to use inexpensive LoRa radios as a
|
||||
long range off-grid communication platform in areas without existing or reliable
|
||||
communications infrastructure. This project is 100% community driven and open
|
||||
source!
|
||||
|
||||
## Quickstart {#module-services-meshtasticd-quickstart}
|
||||
|
||||
A minimal configuration:
|
||||
|
||||
```nix
|
||||
{
|
||||
services.meshtasticd = {
|
||||
enable = true;
|
||||
port = 4403;
|
||||
settings = {
|
||||
Lora = {
|
||||
Module = "auto";
|
||||
};
|
||||
Webserver = {
|
||||
Port = 9443;
|
||||
RootPath = pkgs.meshtastic-web;
|
||||
};
|
||||
General = {
|
||||
MaxNodes = 200;
|
||||
MaxMessageQueue = 100;
|
||||
MACAddressSource = "eth0";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
By default Meshtasticd listens on all network interfaces. The example above
|
||||
binds the daemon to port `4403` and the web UI to `9443`. This module
|
||||
intentionally does not configure an reverse proxy for you, keeping the module
|
||||
focused on the Meshtastic service itself. If you need to restrict access, use
|
||||
firewall rules or put the web UI behind a reverse proxy (e.g.: Caddy, Nginx)
|
||||
that binds to `127.0.0.1` and exposes only the proxy. This approach leaves proxy
|
||||
choice and TLS configuration to the operator while documenting how to securely
|
||||
expose the web UI when required.
|
||||
|
||||
## Configuration {#module-services-meshtasticd-config}
|
||||
|
||||
All available configuration directives are documented in the
|
||||
[standard Meshtastic configuration file](https://github.com/meshtastic/firmware/blob/develop/bin/config-dist.yaml).
|
||||
|
||||
The service uses a dedicated user and group account (`meshtasticd`) by default.
|
||||
If you override the service user, ensure it is a member of the `spi` and `gpio`
|
||||
groups so it can access the required hardware devices, as mandated by
|
||||
Meshtastic’s default `udev` rules.
|
||||
@@ -0,0 +1,124 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.meshtasticd;
|
||||
format = pkgs.formats.yaml { };
|
||||
configFile = format.generate "config.yaml" cfg.settings;
|
||||
in
|
||||
{
|
||||
options.services.meshtasticd = {
|
||||
enable = lib.mkEnableOption "Meshtastic daemon";
|
||||
package = lib.mkPackageOption pkgs "meshtasticd" { };
|
||||
|
||||
user = lib.mkOption {
|
||||
default = "meshtasticd";
|
||||
description = "User meshtasticd runs as.";
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
default = "meshtasticd";
|
||||
description = "Group meshtasticd runs as.";
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 4403;
|
||||
description = "Port to listen on";
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = format.type;
|
||||
example = lib.literalExpression ''
|
||||
Lora = {
|
||||
Module = "auto";
|
||||
};
|
||||
Webserver = {
|
||||
Port = 9443;
|
||||
RootPath = pkgs.meshtastic-web;
|
||||
};
|
||||
General = {
|
||||
MaxNodes = 200;
|
||||
MaxMessageQueue = 100;
|
||||
MACAddressSource = "eth0";
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
The Meshtastic configuration file.
|
||||
|
||||
An example of configuration can be found at <https://github.com/meshtastic/firmware/blob/develop/bin/config-dist.yaml>
|
||||
'';
|
||||
};
|
||||
|
||||
dataDir = lib.mkOption {
|
||||
default = "/var/lib/meshtasticd";
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
The data directory.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# Creation of the `meshtasticd` privilege user.
|
||||
users = {
|
||||
users = lib.mkIf (cfg.user == "meshtasticd") {
|
||||
meshtasticd = {
|
||||
home = cfg.dataDir;
|
||||
description = "meshtasticd-daemon privilege user";
|
||||
group = cfg.group;
|
||||
isSystemUser = true;
|
||||
extraGroups = [
|
||||
"spi"
|
||||
"gpio"
|
||||
];
|
||||
};
|
||||
};
|
||||
groups = lib.mkIf (cfg.group == "meshtasticd") {
|
||||
meshtasticd = { };
|
||||
# These groups are required for udev rules to work properly.
|
||||
spi = { };
|
||||
gpio = { };
|
||||
};
|
||||
};
|
||||
|
||||
# The `meshtasticd` package provides udev rules.
|
||||
services.udev.packages = [
|
||||
cfg.package
|
||||
];
|
||||
|
||||
# Creation of the `meshtasticd` service.
|
||||
# Based on the official meshtasticd service file: https://github.com/meshtastic/firmware/blob/develop/bin/meshtasticd.service
|
||||
systemd.services.meshtasticd = {
|
||||
description = "Meshtastic Native Daemon";
|
||||
after = [
|
||||
"network-online.target"
|
||||
"network.target"
|
||||
];
|
||||
wants = [
|
||||
"network-online.target"
|
||||
"network.target"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
Type = "simple";
|
||||
StateDirectory = "meshtasticd";
|
||||
AmbientCapabilities = [
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
];
|
||||
ExecStart = "${lib.getExe cfg.package} --port=${builtins.toString cfg.port} --fsdir=${cfg.dataDir} --config=${configFile} --verbose";
|
||||
Restart = "always";
|
||||
RestartSec = "3";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -941,6 +941,7 @@ in
|
||||
meilisearch = runTest ./meilisearch.nix;
|
||||
memcached = runTest ./memcached.nix;
|
||||
merecat = runTest ./merecat.nix;
|
||||
meshtasticd = runTest ./networking/meshtasticd.nix;
|
||||
metabase = runTest ./metabase.nix;
|
||||
mihomo = runTest ./mihomo.nix;
|
||||
mimir = runTest ./mimir.nix;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
mainPort = 9445;
|
||||
webPort = 9446;
|
||||
in
|
||||
{
|
||||
name = "meshtasticd";
|
||||
meta.maintainers = [ lib.maintainers.drupol ];
|
||||
|
||||
nodes.machine = {
|
||||
services.meshtasticd = {
|
||||
enable = true;
|
||||
port = mainPort;
|
||||
|
||||
settings = {
|
||||
Lora = {
|
||||
Module = "sim";
|
||||
DIO2_AS_RF_SWITCH = false;
|
||||
spiSpeed = "2000000";
|
||||
};
|
||||
Webserver = {
|
||||
Port = webPort;
|
||||
RootPath = pkgs.meshtastic-web;
|
||||
};
|
||||
General = {
|
||||
MaxNodes = 200;
|
||||
MaxMessageQueue = 100;
|
||||
MACAddressSource = "eth0";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
with subtest("Test meshtasticd service"):
|
||||
machine.wait_for_unit("meshtasticd.service")
|
||||
machine.wait_for_open_port(${builtins.toString mainPort})
|
||||
machine.wait_for_open_port(${builtins.toString webPort})
|
||||
machine.succeed("curl -fvvv -Ls http://localhost:${builtins.toString webPort} | grep -q 'Meshtastic Web Client'")
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
stdenv,
|
||||
lib,
|
||||
fetchurl,
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "meshtastic-web";
|
||||
version = "2.6.7";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/meshtastic/web/releases/download/v${finalAttrs.version}/build.tar";
|
||||
hash = "sha256-o09DYKBIZUOmmN4g3lM1V0kudjq0Wfwn/OqV0ElRRO0=";
|
||||
};
|
||||
|
||||
sourceRoot = ".";
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
gzip -dr .
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out
|
||||
cp -ar . $out/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Meshtastic Web Client/JS Monorepo";
|
||||
homepage = "https://github.com/meshtastic/web";
|
||||
license = lib.licenses.gpl3Plus;
|
||||
platforms = lib.platforms.all;
|
||||
maintainers = with lib.maintainers; [ drupol ];
|
||||
};
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
{ lib, python3Packages }:
|
||||
|
||||
python3Packages.toPythonApplication (
|
||||
python3Packages.meshtastic.overridePythonAttrs (prev: {
|
||||
dependencies = prev.dependencies ++ lib.concatAttrValues prev.optional-dependencies;
|
||||
})
|
||||
)
|
||||
@@ -1,9 +1,13 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchurl,
|
||||
autoPatchelfHook,
|
||||
dpkg,
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
fetchzip,
|
||||
libarchive,
|
||||
pkg-config,
|
||||
platformio-core,
|
||||
writableTmpDirAsHomeHook,
|
||||
bluez,
|
||||
i2c-tools,
|
||||
libX11,
|
||||
libgpiod_1,
|
||||
@@ -11,65 +15,146 @@
|
||||
libusb1,
|
||||
libuv,
|
||||
libxkbcommon,
|
||||
udevCheckHook,
|
||||
ulfius,
|
||||
openssl,
|
||||
gnutls,
|
||||
jansson,
|
||||
zlib,
|
||||
libmicrohttpd,
|
||||
orcania,
|
||||
yder,
|
||||
yaml-cpp,
|
||||
udevCheckHook,
|
||||
versionCheckHook,
|
||||
makeBinaryWrapper,
|
||||
python3Packages,
|
||||
enableDefaultConfig ? false,
|
||||
meshtastic-web, # Only used when `enableDefaultConfig` is set to `true`.
|
||||
nixosTests,
|
||||
}:
|
||||
|
||||
assert builtins.isBool enableDefaultConfig;
|
||||
|
||||
let
|
||||
version = "2.7.16.a597230";
|
||||
|
||||
platformio-deps-native = fetchzip {
|
||||
url = "https://github.com/meshtastic/firmware/releases/download/v${version}/platformio-deps-native-tft-${version}.zip";
|
||||
hash = "sha256-Jo7e6zsCaiJs6NyIRmD6BWJFwbs0xVlUih206ePUpwk=";
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "meshtasticd";
|
||||
version = "2.6.11.25";
|
||||
inherit version;
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://download.opensuse.org/repositories/network:/Meshtastic:/beta/Debian_12/amd64/meshtasticd_${finalAttrs.version}~obs60ec05e~beta_amd64.deb";
|
||||
hash = "sha256-7JCv+1YgsCLwboGE/2f+8iyLLoUsKn3YdJ9Atnfj7Zw=";
|
||||
src = fetchFromGitHub {
|
||||
owner = "meshtastic";
|
||||
repo = "firmware";
|
||||
hash = "sha256-oU3Z8qjBNeNGPGT74VStAPHgsGqsQJKngHJR6m2CBa0=";
|
||||
tag = "v${finalAttrs.version}";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
autoPatchelfHook
|
||||
dpkg
|
||||
];
|
||||
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
libarchive
|
||||
pkg-config
|
||||
# This has been advised by the Meshtastic's developer.
|
||||
# Without it, it will try to install grpcio-tools by itself and fail.
|
||||
(platformio-core.overridePythonAttrs (oldAttrs: {
|
||||
dependencies = oldAttrs.dependencies ++ [
|
||||
python3Packages.grpcio-tools
|
||||
];
|
||||
}))
|
||||
writableTmpDirAsHomeHook
|
||||
makeBinaryWrapper
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
bluez
|
||||
gnutls
|
||||
i2c-tools
|
||||
jansson
|
||||
libX11
|
||||
libgpiod_1
|
||||
libinput
|
||||
libmicrohttpd
|
||||
libusb1
|
||||
libuv
|
||||
libxkbcommon
|
||||
openssl
|
||||
orcania
|
||||
ulfius
|
||||
yaml-cpp
|
||||
yder
|
||||
zlib
|
||||
];
|
||||
|
||||
autoPatchelfIgnoreMissingDeps = [
|
||||
"libyaml-cpp.so.0.7"
|
||||
];
|
||||
preConfigure = ''
|
||||
mkdir -p platformio-deps-native
|
||||
cp -ar ${platformio-deps-native}/. platformio-deps-native
|
||||
chmod +w -R platformio-deps-native
|
||||
|
||||
export PLATFORMIO_CORE_DIR=platformio-deps-native/core
|
||||
export PLATFORMIO_LIBDEPS_DIR=platformio-deps-native/libdeps
|
||||
export PLATFORMIO_PACKAGES_DIR=platformio-deps-native/packages
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
platformio run --environment native-tft
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p {$out,$out/bin}
|
||||
cp -r {usr,lib} $out/
|
||||
install -d $out/share/meshtasticd/config.d
|
||||
install -d $out/share/meshtasticd/available.d
|
||||
cp -R bin/config.d/* $out/share/meshtasticd/available.d
|
||||
|
||||
patchelf --replace-needed libyaml-cpp.so.0.7 libyaml-cpp.so.0.8 $out/usr/bin/meshtasticd
|
||||
install -Dm644 bin/org.meshtastic.meshtasticd.svg -t $out/share/icons/hicolor/scalable/apps/
|
||||
install -Dm644 bin/org.meshtastic.meshtasticd.desktop -t $out/share/applications/
|
||||
install -Dm755 .pio/build/native-tft/program $out/bin/meshtasticd
|
||||
|
||||
ln -s $out/usr/bin/meshtasticd $out/bin/meshtasticd
|
||||
|
||||
substituteInPlace $out/lib/systemd/system/meshtasticd.service \
|
||||
--replace-fail "/usr/bin/meshtasticd" "$out/bin/meshtasticd" \
|
||||
--replace-fail 'User=meshtasticd' 'DynamicUser=yes' \
|
||||
--replace-fail 'Group=meshtasticd' ""
|
||||
install -Dm644 bin/99-meshtasticd-udev.rules -t $out/etc/udev/rules.d
|
||||
''
|
||||
+ lib.optionalString enableDefaultConfig ''
|
||||
install -Dm644 bin/config-dist.yaml $out/share/meshtasticd/config.yaml
|
||||
substituteInPlace $out/share/meshtasticd/config.yaml \
|
||||
--replace-fail "/etc/meshtasticd/config.d" "$out/share/meshtasticd/config.d" \
|
||||
--replace-fail "/etc/meshtasticd/available.d" "$out/share/meshtasticd/available.d"
|
||||
wrapProgram $out/bin/meshtasticd \
|
||||
--add-flags "-c $out/share/meshtasticd/config.yaml"
|
||||
install -Dm644 bin/config.d/MUI/X11_480x480.yaml $out/share/meshtasticd/config.d/MUI.yaml
|
||||
substituteInPlace $out/share/meshtasticd/config.yaml \
|
||||
--replace-fail "/usr/share/meshtasticd/web" "${meshtastic-web}"
|
||||
|
||||
install -d $out/share/meshtasticd/maps
|
||||
for file in pio/libdeps/native-tft/meshtastic-device-ui/maps/*.zip; do
|
||||
bsdtar -xf "$file" --no-same-owner --strip-components=1 -C $out/share/meshtasticd/maps;
|
||||
done
|
||||
''
|
||||
+ ''
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
doInstallCheck = true;
|
||||
nativeInstallCheckInputs = [ udevCheckHook ];
|
||||
nativeInstallCheckInputs = [
|
||||
udevCheckHook
|
||||
versionCheckHook
|
||||
];
|
||||
versionCheckProgramArg = "--version";
|
||||
preVersionCheck = ''
|
||||
version="${lib.versions.major finalAttrs.version}.${lib.versions.minor finalAttrs.version}.${lib.versions.patch finalAttrs.version}"
|
||||
'';
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) meshtasticd;
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Meshtastic daemon for communicating with Meshtastic devices";
|
||||
@@ -77,12 +162,13 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
This package has `udev` rules installed as part of the package.
|
||||
Add `services.udev.packages = [ pkgs.meshtasticd ]` into your NixOS
|
||||
configuration to enable them.
|
||||
|
||||
To enable the default configuration, set the `enableDefaultConfig` parameter to true.
|
||||
'';
|
||||
homepage = "https://github.com/meshtastic/firmware";
|
||||
mainProgram = "meshtasticd";
|
||||
license = lib.licenses.gpl3Plus;
|
||||
platforms = [ "x86_64-linux" ];
|
||||
sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
|
||||
platforms = lib.platforms.linux;
|
||||
maintainers = with lib.maintainers; [ drupol ];
|
||||
};
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user