nixos/home-assistant-matter-hub: init (#513732)

This commit is contained in:
Ilan Joselevich
2026-04-26 17:30:24 +00:00
committed by GitHub
3 changed files with 205 additions and 0 deletions
+1
View File
@@ -728,6 +728,7 @@
./services/home-automation/esphome.nix
./services/home-automation/evcc.nix
./services/home-automation/govee2mqtt.nix
./services/home-automation/home-assistant-matter-hub.nix
./services/home-automation/home-assistant.nix
./services/home-automation/homebridge.nix
./services/home-automation/matter-server.nix
@@ -0,0 +1,100 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.home-assistant-matter-hub;
settingsFormat = pkgs.formats.json { };
configFile = settingsFormat.generate "home-assistant-matter-hub.json" cfg.settings;
in
{
meta.maintainers = with lib.maintainers; [
kranzes
marie
];
options.services.home-assistant-matter-hub = {
enable = lib.mkEnableOption "home-assistant-matter-hub, a Matter bridge for Home Assistant";
package = lib.mkPackageOption pkgs "home-assistant-matter-hub" { };
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to open the Matter commissioning ports (UDP/TCP 5540) in the
firewall.
'';
};
accessTokenFile = lib.mkOption {
type = lib.types.externalPath;
example = "/run/secrets/home-assistant-matter-hub-token";
description = ''
Path to a file containing a Home Assistant long-lived access token.
The file is loaded as a systemd credential and read into
`HAMH_HOME_ASSISTANT_ACCESS_TOKEN` at service start.
'';
};
settings = lib.mkOption {
type = lib.types.submodule {
freeformType = settingsFormat.type;
options = {
homeAssistantUrl = lib.mkOption {
type = lib.types.str;
example = lib.literalExpression "config.services.home-assistant.config.homeassistant.internal_url";
description = "HTTP URL of the Home Assistant instance to bridge.";
};
httpPort = lib.mkOption {
type = lib.types.port;
default = 8482;
description = "Port the web interface listens on.";
};
};
};
default = { };
example = lib.literalExpression ''
{
homeAssistantUrl = config.services.home-assistant.config.homeassistant.internal_url;
}
'';
description = ''
Configuration written to a JSON file and passed to
`home-assistant-matter-hub start --config`. Keys use camelCase, matching
the long-form CLI flags. See
<https://riddix.github.io/home-assistant-matter-hub/getting-started/installation#23-configuration-options>
for the full list of options.
'';
};
};
config = lib.mkIf cfg.enable {
networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ 5540 ];
allowedUDPPorts = [ 5540 ];
};
systemd.services.home-assistant-matter-hub = {
description = "Home Assistant Matter Hub";
documentation = [ "https://riddix.github.io/home-assistant-matter-hub/" ];
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
script = ''
export HAMH_HOME_ASSISTANT_ACCESS_TOKEN=$(systemd-creds cat HAMH_HOME_ASSISTANT_ACCESS_TOKEN)
exec ${lib.getExe cfg.package} start --config=${configFile} --storage-location="$1"
'';
scriptArgs = "%S/home-assistant-matter-hub";
serviceConfig = {
LoadCredential = [ "HAMH_HOME_ASSISTANT_ACCESS_TOKEN:${cfg.accessTokenFile}" ];
DynamicUser = true;
StateDirectory = "home-assistant-matter-hub";
};
};
};
}
@@ -0,0 +1,104 @@
{
lib,
stdenvNoCC,
fetchFromGitHub,
nodejs,
pnpm_10,
pnpmConfigHook,
fetchPnpmDeps,
makeWrapper,
}:
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "home-assistant-matter-hub";
version = "2.0.41";
src = fetchFromGitHub {
owner = "RiDDiX";
repo = "home-assistant-matter-hub";
tag = "v${finalAttrs.version}";
hash = "sha256-+W0HjULERuW+RY7938xGnEXwmCpkumLpUlZmvfuhX2Y=";
};
# The bundled cli.js imports transitive dependencies (e.g. @noble/curves)
# directly, so we need a flat node_modules tree for Node's resolver to
# find them.
pnpmInstallFlags = [ "--shamefully-hoist" ];
pnpmWorkspaces = [ "home-assistant-matter-hub..." ];
pnpmDeps = fetchPnpmDeps {
inherit (finalAttrs)
pname
version
src
pnpmInstallFlags
pnpmWorkspaces
;
fetcherVersion = 3;
hash = "sha256-1DaR4q1QH07UR+EchfDI92bTdRY4C2IaGIRj426DURI=";
};
__structuredAttrs = true;
strictDeps = true;
# Workspace package.json files all carry "0.0.0"; the real version is
# injected at release time via APP_VERSION (consumed by vite for the
# frontend bundle and by the backend at runtime).
env.APP_VERSION = finalAttrs.version;
nativeBuildInputs = [
nodejs
pnpm_10
pnpmConfigHook
makeWrapper
];
buildPhase = ''
runHook preBuild
pnpm --filter home-assistant-matter-hub... run build
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin $out/share/apps/home-assistant-matter-hub
tar -xf apps/home-assistant-matter-hub/package.tgz \
--strip-components=1 \
-C $out/share/apps/home-assistant-matter-hub
# pnpm cannot recursively prune monorepos, so we follow pnpm's
# recommendation of removing all node_modules and reinstalling
# only the production dependencies we need.
find . -name node_modules -type d -prune -exec rm -rf {} +
pnpm install --offline --prod --filter-prod home-assistant-matter-hub --shamefully-hoist
# Workspace symlinks under apps/home-assistant-matter-hub/node_modules use
# relative paths into the top-level node_modules/.pnpm store, so we keep
# the original directory layout under $out/share.
mv node_modules $out/share/
mv apps/home-assistant-matter-hub/node_modules $out/share/apps/home-assistant-matter-hub/
makeWrapper ${lib.getExe nodejs} "$out/bin/home-assistant-matter-hub" \
--add-flags "$out/share/apps/home-assistant-matter-hub/dist/backend/cli.js" \
--set NODE_ENV production \
--set APP_VERSION ${finalAttrs.version}
runHook postInstall
'';
meta = {
description = "Publish your home-assistant instance using Matter";
homepage = "https://riddix.github.io/home-assistant-matter-hub/";
changelog = "https://github.com/RiDDiX/home-assistant-matter-hub/releases/tag/v${finalAttrs.version}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [
kranzes
marie
];
mainProgram = "home-assistant-matter-hub";
inherit (nodejs.meta) platforms;
};
})