Loading nixos/modules/module-list.nix +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading nixos/modules/services/home-automation/home-assistant-matter-hub.nix 0 → 100644 +100 −0 Original line number Diff line number Diff line { 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"; }; }; }; } pkgs/by-name/ho/home-assistant-matter-hub/package.nix 0 → 100644 +104 −0 Original line number Diff line number Diff line { 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; }; }) Loading
nixos/modules/module-list.nix +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
nixos/modules/services/home-automation/home-assistant-matter-hub.nix 0 → 100644 +100 −0 Original line number Diff line number Diff line { 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"; }; }; }; }
pkgs/by-name/ho/home-assistant-matter-hub/package.nix 0 → 100644 +104 −0 Original line number Diff line number Diff line { 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; }; })