nixos/matter-server: fix fetching of PAA certificates from DCL

* Removes PAA certs patch, since that patch is no longer needed since matter-server no longer crashes when there are no certs present and network is unavailable.
* Saves fetched PAA certs to /var/cache/matter-server/certs
* Mounts /etc/resolv.conf for DNS lookups
* Specifies cacert bundle for SSL handshakes

Signed-off-by: Matt Leon <ml@mattleon.com>
This commit is contained in:
Matt Leon
2026-03-21 16:36:44 -04:00
parent 85106a26f4
commit 15d91b0af9
4 changed files with 44 additions and 114 deletions

View File

@@ -14,7 +14,7 @@ in
{
meta.maintainers = with lib.maintainers; [ leonm1 ];
options.services.matter-server = with lib.types; {
options.services.matter-server = {
enable = lib.mkEnableOption "Matter-server";
package = lib.mkPackageOption pkgs "python-matter-server" { };
@@ -44,10 +44,10 @@ in
};
extraArgs = lib.mkOption {
type = listOf str;
default = [ ];
type = lib.types.attrs;
default = { };
description = ''
Extra arguments to pass to the matter-server executable.
Attribute set of extra arguments to pass to the matter-server executable.
See <https://github.com/home-assistant-libs/python-matter-server?tab=readme-ov-file#running-the-development-server> for options.
'';
};
@@ -62,41 +62,52 @@ in
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
description = "Matter Server";
environment.HOME = storagePath;
environment = {
HOME = storagePath;
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
};
script = ''
# `python-matter-server` writes to /data even when a storage-path is
# specified. This symlinks /data at the systemd-managed
# /var/lib/matter-server, so all files get dropped into the state
# directory.
ln -s $STATE_DIRECTORY $RUNTIME_DIRECTORY/data
# Create directories to hold certificates and OTA updates.
CERT_DIR="$CACHE_DIRECTORY/certs"
mkdir -p "$CERT_DIR"
OTA_UPDATE_DIR="$CACHE_DIRECTORY/updates"
mkdir -p "$OTA_UPDATE_DIR"
"${lib.getExe cfg.package}" ${
lib.concatStringsSep " " (
lib.cli.toCommandLineGNU { } (
{
port = cfg.port;
vendorid = vendorId;
storage-path = storagePath;
log-level = cfg.logLevel;
paa-root-cert-dir = "$CERT_DIR";
ota-provider-dir = "$OTA_UPDATE_DIR";
}
// cfg.extraArgs
)
)
}
'';
serviceConfig = {
ExecStart = (
lib.concatStringsSep " " [
# `python-matter-server` writes to /data even when a storage-path
# is specified. This symlinks /data at the systemd-managed
# /var/lib/matter-server, so all files get dropped into the state
# directory.
"${pkgs.bash}/bin/sh"
"-c"
"'"
"${pkgs.coreutils}/bin/ln -s %S/matter-server/ %t/matter-server/root/data"
"&&"
"${cfg.package}/bin/matter-server"
"--port"
(toString cfg.port)
"--vendorid"
vendorId
"--storage-path"
storagePath
"--log-level"
"${cfg.logLevel}"
"${lib.escapeShellArgs cfg.extraArgs}"
"'"
]
);
# Start with a clean root filesystem, and allowlist what the container
# is permitted to access.
# See https://discourse.nixos.org/t/hardening-systemd-services/17147/14.
RuntimeDirectory = [ "matter-server/root" ];
RootDirectory = "%t/matter-server/root";
CacheDirectory = [ "matter-server" ];
# Allowlist /nix/store (to allow the binary to find its dependencies)
# and dbus.
BindReadOnlyPaths = "/nix/store /run/dbus";
BindReadOnlyPaths = [
"/nix/store" # To allow the binary to find its dependencies.
"/run/dbus"
"/etc/resolv.conf" # For DNS resolution.
];
# Let systemd manage `/var/lib/matter-server` for us inside the
# ephemeral TemporaryFileSystem.
StateDirectory = storageDir;

View File

@@ -30,7 +30,7 @@ in
start_all()
machine.wait_for_unit("matter-server.service", timeout=20)
machine.wait_for_open_port(1234, timeout=20)
machine.wait_for_open_port(1234, timeout=100)
with matter_server_running: # type: ignore[union-attr]
with subtest("Check websocket server initialized"):

View File

@@ -4,7 +4,6 @@
fetchFromGitHub,
pythonOlder,
stdenvNoCC,
replaceVars,
buildNpmPackage,
python,
home-assistant-chip-wheels,
@@ -46,23 +45,6 @@ let
hash = "sha256-vnI57h/aesnaDYorq1PzcMCLmV0z0ZBJvMg4Nzh1Dtc=";
};
paaCerts = stdenvNoCC.mkDerivation {
pname = "matter-server-paa-certificates";
inherit (home-assistant-chip-wheels) version src;
dontConfigure = true;
dontBuild = true;
installPhase = ''
runHook preInstall
mkdir -p $out
cp connectedhomeip/credentials/development/paa-root-certs/* $out/
runHook postInstall
'';
};
# 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
@@ -119,12 +101,6 @@ buildPythonPackage rec {
disabled = pythonOlder "3.12";
patches = [
(replaceVars ./link-paa-root-certs.patch {
paacerts = paaCerts;
})
];
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail 'version = "0.0.0"' 'version = "${version}"'

View File

@@ -1,57 +0,0 @@
From f45cf9898f2e5a3a4c2b73a9ed84c4a037a85a1e Mon Sep 17 00:00:00 2001
From: Matt Leon <ml@mattleon.com>
Date: Sat, 1 Jun 2024 23:28:41 -0400
Subject: [PATCH] Symlink PAA root certificates to nix store
---
matter_server/server/const.py | 2 ++
matter_server/server/helpers/paa_certificates.py | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/matter_server/server/const.py b/matter_server/server/const.py
index 8cca3cf..43f02f5 100644
--- a/matter_server/server/const.py
+++ b/matter_server/server/const.py
@@ -14,6 +14,8 @@ DATA_MODEL_SCHEMA_VERSION = 6
# Keep default location inherited from early version of the Python
# bindings.
DEFAULT_PAA_ROOT_CERTS_DIR: Final[pathlib.Path] = (
+ pathlib.Path("@paacerts@"))
+(
pathlib.Path(__file__)
.parent.resolve()
.parent.resolve()
diff --git a/matter_server/server/helpers/paa_certificates.py b/matter_server/server/helpers/paa_certificates.py
index de60c78..185e54c 100644
--- a/matter_server/server/helpers/paa_certificates.py
+++ b/matter_server/server/helpers/paa_certificates.py
@@ -105,6 +105,8 @@ async def fetch_dcl_certificates(
base_url: str,
) -> int:
"""Fetch DCL PAA Certificates."""
+ return 0
+
fetch_count: int = 0
try:
@@ -151,6 +153,8 @@ async def fetch_dcl_certificates(
async def fetch_git_certificates(paa_root_cert_dir: Path) -> int:
"""Fetch Git PAA Certificates."""
+ return 0
+
fetch_count = 0
LOGGER.info("Fetching the latest PAA root certificates from Git.")
@@ -185,6 +189,8 @@ async def fetch_certificates(
fetch_production_certificates: bool = True,
) -> int:
"""Fetch PAA Certificates."""
+ return 0
+
loop = asyncio.get_running_loop()
paa_root_cert_dir_version = paa_root_cert_dir / ".version"
--
2.44.1