python-matter-server: bundle dashboard (#446981)

This commit is contained in:
dotlambda
2025-11-06 16:27:29 +00:00
committed by GitHub
4 changed files with 83 additions and 11 deletions

View File

@@ -444,6 +444,8 @@ and [release notes for v18](https://goteleport.com/docs/changelog/#1800-070325).
- `services.xserver.desktopManager.deepin` and associated packages have been removed due to being unmaintained. See issue [#422090](https://github.com/NixOS/nixpkgs/issues/422090) for more details. - `services.xserver.desktopManager.deepin` and associated packages have been removed due to being unmaintained. See issue [#422090](https://github.com/NixOS/nixpkgs/issues/422090) for more details.
- `services.matter-server` now hosts a debug dashboard on the configured port. Open the port on the firewall with `services.matter-server.openFirewall`.
- The new option [networking.ipips](#opt-networking.ipips) has been added to create IP within IP kind of tunnels (including 4in6, ip6ip6 and ipip). - The new option [networking.ipips](#opt-networking.ipips) has been added to create IP within IP kind of tunnels (including 4in6, ip6ip6 and ipip).
With the existing [networking.sits](#opt-networking.sits) option (6in4), it is now possible to create all combinations of IPv4 and IPv6 encapsulation. With the existing [networking.sits](#opt-networking.sits) option (6in4), it is now possible to create all combinations of IPv4 and IPv6 encapsulation.

View File

@@ -25,6 +25,12 @@ in
description = "Port to expose the matter-server service on."; description = "Port to expose the matter-server service on.";
}; };
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to open the port in the firewall.";
};
logLevel = lib.mkOption { logLevel = lib.mkOption {
type = lib.types.enum [ type = lib.types.enum [
"critical" "critical"
@@ -48,6 +54,8 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
systemd.services.matter-server = { systemd.services.matter-server = {
after = [ "network-online.target" ]; after = [ "network-online.target" ];
before = [ "home-assistant.service" ]; before = [ "home-assistant.service" ];

View File

@@ -16,6 +16,7 @@ in
services.matter-server = { services.matter-server = {
enable = true; enable = true;
port = 1234; port = 1234;
openFirewall = true;
}; };
}; };
}; };
@@ -43,6 +44,9 @@ in
with subtest("Check storage directory is created"): with subtest("Check storage directory is created"):
machine.succeed("ls /var/lib/matter-server/chip.json") machine.succeed("ls /var/lib/matter-server/chip.json")
with subtest("Check dashboard loads"):
machine.succeed("curl -f 127.0.0.1:1234")
with subtest("Check systemd hardening"): with subtest("Check systemd hardening"):
_, output = machine.execute("systemd-analyze security matter-server.service | grep -v ''") _, output = machine.execute("systemd-analyze security matter-server.service | grep -v ''")
machine.log(output) machine.log(output)

View File

@@ -5,6 +5,8 @@
pythonOlder, pythonOlder,
stdenvNoCC, stdenvNoCC,
replaceVars, replaceVars,
buildNpmPackage,
python,
# build # build
setuptools, setuptools,
@@ -24,14 +26,25 @@
# tests # tests
aioresponses, aioresponses,
python,
pytest, pytest,
pytest-aiohttp, pytest-aiohttp,
pytest-cov-stub, pytest-cov-stub,
pytestCheckHook, pytestCheckHook,
# build options
withDashboard ? true,
}: }:
let let
version = "8.1.1";
src = fetchFromGitHub {
owner = "home-assistant-libs";
repo = "python-matter-server";
tag = version;
hash = "sha256-vTJGe6OGFM+q9+iovsQMPwkrHNg2l4pw9BFEtSA/vmA=";
};
paaCerts = stdenvNoCC.mkDerivation rec { paaCerts = stdenvNoCC.mkDerivation rec {
pname = "matter-server-paa-certificates"; pname = "matter-server-paa-certificates";
version = "1.4.0.0"; version = "1.4.0.0";
@@ -52,22 +65,63 @@ let
runHook postInstall runHook postInstall
''; '';
}; };
in
# Maintainer note: building the dashboard requires a python environment with a
# built version of python-matter-server. To support bundling the dashboard
# with the python-matter-server, the build is parameterized to build without
# a dependency on the dashboard, breaking a cyclical dependency. First,
# python-matter-server is built without the dashboard, then the dashboard is
# built, then python-matter-server is built again with the dashboard.
matterServerDashboard =
let
pythonWithChip = python.withPackages (ps: [
ps.home-assistant-chip-clusters
(ps.python-matter-server.override { withDashboard = false; })
]);
in
buildNpmPackage {
pname = "python-matter-server-dashboard";
inherit src version;
npmDepsHash = "sha256-IgI1H3VlTq66duplVQqL67SpgxPF2MOowDn+ICMXCik=";
prePatch = ''
${pythonWithChip.interpreter} scripts/generate_descriptions.py
# cd before the patch phase sets up the npm install hook to find the
# package.json. The script would need to be patched in order to be used
# with sourceRoot.
cd "dashboard"
'';
# This package does not contain a normal `npm build` step.
buildPhase = ''
env NODE_ENV=production npm exec -- tsc
env NODE_ENV=production npm exec -- rollup -c
'';
installPhase = ''
runHook preInstall
install -Dt "$out/" public/*
# Copy recursive directory structure, which install does not do.
cp -r dist/web/* "$out/"
runHook postInstall
'';
};
in
buildPythonPackage rec { buildPythonPackage rec {
pname = "python-matter-server"; pname = if withDashboard then "python-matter-server" else "python-matter-server-without-dashboard";
version = "8.1.1"; inherit
src
version
;
pyproject = true; pyproject = true;
disabled = pythonOlder "3.12"; disabled = pythonOlder "3.12";
src = fetchFromGitHub {
owner = "home-assistant-libs";
repo = "python-matter-server";
tag = version;
hash = "sha256-vTJGe6OGFM+q9+iovsQMPwkrHNg2l4pw9BFEtSA/vmA=";
};
patches = [ patches = [
(replaceVars ./link-paa-root-certs.patch { (replaceVars ./link-paa-root-certs.patch {
paacerts = paaCerts; paacerts = paaCerts;
@@ -77,6 +131,10 @@ buildPythonPackage rec {
postPatch = '' postPatch = ''
substituteInPlace pyproject.toml \ substituteInPlace pyproject.toml \
--replace-fail 'version = "0.0.0"' 'version = "${version}"' --replace-fail 'version = "0.0.0"' 'version = "${version}"'
''
+ lib.optionalString withDashboard ''
substituteInPlace "matter_server/server/server.py" \
--replace-fail 'Path(__file__).parent.joinpath("../dashboard/")' 'Path("${matterServerDashboard}")'
''; '';
build-system = [ build-system = [