Home Assistant: Difference between revisions

Hexa (talk | contribs)
HAOS in Virtualbox Screenshot
Hexa (talk | contribs)
m url fix
 
(34 intermediate revisions by 11 users not shown)
Line 5: Line 5:
NixOS provides native support for [https://www.home-assistant.io/faq/ha-vs-hassio/ Home Assistant Core] and offers integration facilities for most pieces of its comprehensive ecosystem:
NixOS provides native support for [https://www.home-assistant.io/faq/ha-vs-hassio/ Home Assistant Core] and offers integration facilities for most pieces of its comprehensive ecosystem:


* As of the 2024.7.1 release we support roughly 87.6% (1107/1264) of the built-in integrations
* As of the 2026.2.0 release we support over 98% (1375/1394) of the built-in integrations
* We support [https://github.com/NixOS/nixpkgs/tree/master/pkgs/servers/home-assistant/custom-components custom components] through the <code>[https://search.nixos.org/options?channel=unstable&show=services.home-assistant.customComponents&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.customComponents services.home-assistant.customComponents]</code> option
* We support [https://github.com/NixOS/nixpkgs/tree/master/pkgs/servers/home-assistant/custom-components custom components] through the <code>[https://search.nixos.org/options?channel=unstable&show=services.home-assistant.customComponents&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.customComponents services.home-assistant.customComponents]</code> option
* We support source-built [https://github.com/NixOS/nixpkgs/tree/master/pkgs/servers/home-assistant/custom-lovelace-modules custom lovelace modules] mostly through [https://search.nixos.org/options?channel=unstable&show=services.home-assistant.customLovelaceModules&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.customLovelaceModules services.home-assistant.customLovelaceModules] option
* We support source-built [https://github.com/NixOS/nixpkgs/tree/master/pkgs/servers/home-assistant/custom-lovelace-modules custom lovelace modules] mostly through [https://search.nixos.org/options?channel=unstable&show=services.home-assistant.customLovelaceModules&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.customLovelaceModules services.home-assistant.customLovelaceModules] option
* We do not support [https://www.home-assistant.io/addons/ addons], which are used to deploy additional services, that are configurable from Home Assistant on their operating system
* We do not support [https://www.home-assistant.io/addons/ apps] (previously addons), which are used to deploy additional services, that are configurable from Home Assistant on their operating system
** NixOS has native support for various services, that integrate with Home Assistant, e.g. [[Mosquitto]], [[Wyoming]], [[zigbee2mqtt]], [[Z-Wave JS]]
** NixOS has native support for various services, that integrate with Home Assistant, e.g. [[EVCC]], [[Frigate]], [[Mosquitto]], [[Music-Assistant]], [[Wyoming]], [[zigbee2mqtt]], [[Z-Wave JS]]


== Support ==
== Support ==
Line 27: Line 27:
Example:
Example:
* [https://myme.no/posts/2021-11-25-nixos-home-assistant.html NixOS: Headless Home Assistant VM (myme.no)] using libvirt
* [https://myme.no/posts/2021-11-25-nixos-home-assistant.html NixOS: Headless Home Assistant VM (myme.no)] using libvirt
* [https://balisong.dev/blog/running-home-assistant-os-as-a-vm-in-a-nixos-host/ Running Home Assistant OS as a VM in a NixOS Host] using incus


=== OCI container ===
=== OCI container ===
Line 55: Line 56:
== Native installation ==
== Native installation ==


* There is full support for configuring the through the <code>[https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.config services.home-assistant.config]</code> option.
* There is full support for the YAML configuration through the <code>[https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.config services.home-assistant.config]</code> option.
* This is also the case for the [https://www.home-assistant.io/dashboards/dashboards/#adding-more-dashboards-with-yaml Lovelace YAML configuration] through the [https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.lovelace <code>services.home-assistant.lovelace</code>] option.
* This is also the case for the [https://www.home-assistant.io/dashboards/dashboards/#adding-more-dashboards-with-yaml Lovelace YAML configuration] through the [https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.lovelace <code>services.home-assistant.lovelace</code>] option.
** Custom Lovelace modules can be configured through [https://search.nixos.org/options?channel=unstable&show=services.home-assistant.customLovelaceModules&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.customLovelaceModules <code>services.home-assistant.customLovelaceModules</code>]. The [https://www.home-assistant.io/dashboards/dashboards/#resources <code>resources</code>] section of your Lovelace configuration will automatically be populated.
** Custom Lovelace modules can be configured through [https://search.nixos.org/options?channel=unstable&show=services.home-assistant.customLovelaceModules&from=0&size=50&sort=relevance&type=packages&query=services.home-assistant.customLovelaceModules <code>services.home-assistant.customLovelaceModules</code>]. The [https://www.home-assistant.io/dashboards/dashboards/#resources <code>resources</code>] section of your Lovelace configuration will automatically be populated.
Line 65: Line 66:
The following is a minimal configuration, that has all the dependencies that are required to complete the initial configuration flow, that creates your first user:
The following is a minimal configuration, that has all the dependencies that are required to complete the initial configuration flow, that creates your first user:


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
{
{
   services.home-assistant = {
   services.home-assistant = {
Line 71: Line 72:
     extraComponents = [
     extraComponents = [
       # Components required to complete the onboarding
       # Components required to complete the onboarding
       "esphome"
       "analytics"
      "google_translate"
       "met"
       "met"
       "radio_browser"
       "radio_browser"
      "shopping_list"
      # Recommended for fast zlib compression
      # https://www.home-assistant.io/integrations/isal
      "isal"
     ];
     ];
     config = {
     config = {
Line 82: Line 88:
   };
   };
}
}
</syntaxHighlight>
</syntaxhighlight>


=== Imperative configuration ===
=== Imperative configuration ===
Line 106: Line 112:


=== Firewalling ===
=== Firewalling ===
If not using a reverse-proxy, and you just want unencrypted access on a local network don't forget to update your firewall configuration to expose the port home-assistant is running on.
Home Assistant by default listens on port 8123. It is customary to put services behind a [[Home Assistant#Reverse Proxying with nginx|reverse-proxy]], which allows sharing ports 80/443 (http/https) and offers TLS termination.
 
If you don't plan on using a reverse-proxy, you can allow unencrypted access by opening up the port home-assistant is running on in your firewall. This is not generally recommended, since credentials will be transmitted in plain text and browsers tend to limit certain functionality (e.g. geolocation) to HTTPS.
 
<syntaxhighlight lang="nix">
{
  config,
  ...
}:


<syntaxHighlight lang=nix>
{
{
   networking.firewall.allowedTCPPorts = [ <other ports> 8123 ];
   networking.firewall.allowedTCPPorts = [
    config.services.home-assistant.config.http.server_port
  ];
}
}
</syntaxHighlight>
</syntaxhighlight>
 
===== First start =====


On your first start you may see multiple <code><nowiki>ModuleNotFoundError</nowiki></code> in Home Assistants journal log. These are dependencies required to set up devices Home Assistant already found on the network.
=== First start ===
On your first start you may see multiple <code><nowiki>ModuleNotFoundError</nowiki></code> in Home Assistants journal log. These are dependencies required to set up devices Home Assistant already discovered on the local network.


The appropriate component to load can be looked up in the <code><nowiki>component-packages.nix</nowiki></code> file, that gets auto-generated as part of the packaging process.
The appropriate component to load can be looked up in the <code>[https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/component-packages.nix component-packages.nix]</code> file, that gets auto-generated as part of the packaging process.


For example, we can map the following error to
For example, we can map the following error to
Line 139: Line 153:
     [...]
     [...]
</syntaxHighlight>
</syntaxHighlight>
* https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/component-packages.nix


==== Using components without YAML configuration ====
==== Using components without YAML configuration ====


When a component has no YAML configuration its dependencies can in theory be installed by mentioning the component name in <code><nowiki>services.home-assistant.config.wled = {};</nowiki></code>. This is deprecated, since Home Assistant will usually complain about the config having been migrated into the graphical user interface.
When a component offers no YAML configuration its dependencies could in theory be installed by mentioning its component name in <code><nowiki>services.home-assistant.config.wled = {};</nowiki></code>. This is deprecated, since Home Assistant will usually complain about the config having been migrated into the graphical user interface.


In recent versions of the home-assistant this use case has become more prominent and therefore received a more straightforward implementation, that also ensures that the component is still provided by Home Assistant.
In recent versions of the home-assistant this use case has become more prominent and therefore received a more straightforward implementation, that also ensures that the component is still provided by Home Assistant.
Line 156: Line 168:
</syntaxHighlight>
</syntaxHighlight>


==== Making additional python packages available ====
==== Provide additional Python packages to Home Assistant ====


We control the dependencies we pass into the Home Assistant python environment through module options that make the dependencies available, when their relative component was declaratively mentioned.
We control the dependencies we pass into the Home Assistant python environment through module options that make the dependencies available, when their relative component was declaratively mentioned.
Line 185: Line 197:
We provide a way to declaratively manage custom lovelace modules through the NixOS module with the [https://search.nixos.org/options?channel=unstable&show=services.home-assistant.customLovelaceModules&from=0&size=50&sort=relevance&type=packages&query=home-assistant services.home-assistant.customLovelaceModules] option.
We provide a way to declaratively manage custom lovelace modules through the NixOS module with the [https://search.nixos.org/options?channel=unstable&show=services.home-assistant.customLovelaceModules&from=0&size=50&sort=relevance&type=packages&query=home-assistant services.home-assistant.customLovelaceModules] option.


Custom components can be found under [https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=home-assistant-custom-lovelace-modules pkgs.home-assistant-custom-lovelace-modules].
When a custom module is configured, the generated Home Assistant configuration file (eg. <code>/var/lib/hass/configuration.yaml</code>) will list the module in the <code>lovelace</code> config section as a new resource. If your lovelace configuration mode is <code>yaml</code>, the custom module should be loaded automatically.  
 
=== Reusing existing YAML configuration ===


The module also supports passing it an existing configuration, however that comes with certain drawbacks. For example we cannot automatically detect the components, that your configuration requires. In that scenario you will need to resolve dependencies manually using the packages <code>extraComponents</code> parameter. Also you will be unable to reuse configuration values between parts of your NixOS configuration. A barebones setup to get you started may look like this:
However, if your lovelace configuration mode is <code>storage</code> (the default), then the Home Assistant lovelace module will ignore the custom module resource. In that case you additionally need to add the custom module through the lovelace UI in the Resources tab with its path like <code>/local/nixos-lovelace-modules/<module-entrypoint></code>.
 
<syntaxHighlight lang=nix>
{
  services.home-assistant = {
    enable = true;
    # Pass the path to the directory where your configuration.yaml
    # resides, /var/lib/hass might be a good location.
    configDir = /var/lib/hass;
    # Override the package to handle dependency management manually
    package = (pkgs.home-assistant.override {
      # https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/component-packages.nix
      extraComponents = [
        "default_config"
        "esphome"
        "met"
      ];
      extraPackages = ps: with ps; [
        # Are you using a database server for your recorder?
        # https://www.home-assistant.io/integrations/recorder/
        #mysqlclient
        #psycopg2
      ];
    })
  };
}
</syntaxHighlight>


You may find the following script helpful. It looks up missing dependencies from the <code>home-assistant.service</code> systemd unit journal: https://gist.github.com/AngryAnt/74c047a2b8438517c822ffdd9663aa57
Available custom components can be found under [https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=home-assistant-custom-lovelace-modules pkgs.home-assistant-custom-lovelace-modules].


= Running a recent version using an overlay =  
= Tracking the latest release =  


Home Assistant is a fast-paced open source project, that currently features one major release every month, and a handful of minor ones in between. Firmwares and API endpoints tend to change from time to  time, so Home Assistant and its bindings need to keep up to keep things work. The version we provide at the branch off is just a snapshot in time, and does not receive any updates, because there would just be too many dependencies to backport. But with NixOS it is still possible to use the version in nixpkgs/unstable by creating an overlay and using the module from nixos-unstable.
Home Assistant is a fast-paced open source project, that currently features one major release every month, and a handful of minor ones in between. Firmwares and API endpoints tend to change from time to  time, so Home Assistant and its bindings need to keep up to keep things work. The version we provide at the branch off is just a snapshot in time, and does not receive any updates, because there would just be too many dependencies and breaking changes to backport. But with NixOS it is still possible to use the version in nixpkgs/unstable by creating an overlay and using the module from [[Channel branches|nixos-unstable]].


<syntaxHighlight lang=nix>
<syntaxHighlight lang=nix>
Line 281: Line 265:
Home Assistant supports PostgreSQL as a database backend for, among other things, its logger and history components. It's a lot more scalable and typically provides faster response times than the SQLite database, that is used by default.
Home Assistant supports PostgreSQL as a database backend for, among other things, its logger and history components. It's a lot more scalable and typically provides faster response times than the SQLite database, that is used by default.


Remember to make backups of your database, for Home Assistant is becoming more and more stateful and has moved away from a completely declarative YAML configuration for new and core components.
<syntaxhighlight lang="nix">
 
Also note that when overriding the package you may want to disable install checks as they tend to take a long time to complete.
 
<syntaxHighlight lang=nix>
   services.home-assistant = {
   services.home-assistant = {
     package = (pkgs.home-assistant.override {
     extraPackages = ps: with ps; [ psycopg2 ];
      extraPackages = py: with py; [ psycopg2 ];
    }).overrideAttrs (oldAttrs: {
      doInstallCheck = false;
    });
     config.recorder.db_url = "postgresql://@/hass";
     config.recorder.db_url = "postgresql://@/hass";
   };
   };
Line 303: Line 279:
     }];
     }];
   };
   };
</syntaxHighlight>
</syntaxhighlight>


== Updating Zigbee Firmware over the air ==
== Updating Zigbee Firmware over the air ==
Line 317: Line 293:
</syntaxHighlight>
</syntaxHighlight>


== Combine declarative and UI defined automations ==
== Automations, Scenes, and Scripts from the UI ==


You can also declaratively define your automations while still being able to define them in Home Assistant UI. Automations defined in UI are stored in <code>/var/lib/hass/automations.yaml</code>. If you are not planning on using UI defined automations, then you can define them under  <code>services.home-assistant.config.automation</code>, otherwise split them into <code>services.home-assistant.config."automation manual"</code> and <code>services.home-assistant.config."automation ui"</code>, like so:
These can be created from the user interface, but the files generated from it need to be included in your configuration.<syntaxhighlight lang="nixos">
<syntaxHighlight lang=nix>
{
   services.home-assistant.config =
   services.home-assistant.config = {
  {
    "automation manual" = [
      {
        alias = "living room plug off";
        trigger = {
          platform = "time";
          at = "22:00";
        };
        action = {
          type = "turn_off";
          device_id = "someID"; #Inspect yaml of automation created in UI
          entity_id = "switch.living_room_plug";
          domain = "switch";
        };
      }
    ];
     "automation ui" = "!include automations.yaml";
     "automation ui" = "!include automations.yaml";
}
    "scene ui" = "!include scenes.yaml";
</syntaxHighlight>
    "script ui" = "!include scripts.yaml";
 
  };
== Combine declarative and UI defined scenes ==
};
Same as with automations, scenes can also be configured both declaratively and from within the UI:
</syntaxhighlight>It is also possible to mix declarative and generated configuration for these components, by creating multiple configuration sections with the automation, scenes, or scripts prefix:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
services.home-assistant.config."scene manual" = [
services.home-assistant.config = {
  # declarative scenes go here
  "automation nixos" = [
];
    # YAML automations go here
services.home-assistant.config."scene ui" = "!include scenes.yaml";
  ];
  "automation ui" = "!include automations.yaml";
}
</syntaxhighlight>
</syntaxhighlight>


== More Declarative Nix Configuration Examples ==
= Examples =


=== Entity Customization ===
=== Entity Customization ===
Line 456: Line 418:
         {
         {
           alias = "Name To Display in Automations List";
           alias = "Name To Display in Automations List";
           trigger = {
           triggers = {
             platform = "state";
             trigger = "state";
             entity_id = "binary_sensor.someid1";
             entity_id = "binary_sensor.someid1";
             to = "off";
             to = "off";
             for = "00:10:00";
             for = "00:10:00";
           };
           };
           condition = {
           conditions = {
             condition = "state";
             condition = "state";
             entity_id = "binary_sensor.someid2";
             entity_id = "binary_sensor.someid2";
             state = "on";
             state = "on";
           };
           };
           action = {
           actions = {
             service = "light.turn_off";
             action = "light.turn_off";
             entity_id = "light.someid";
             entity_id = "light.someid";
           };
           };
Line 478: Line 440:
         {
         {
           alias = "Name in Automations GUI";
           alias = "Name in Automations GUI";
           trigger = {
           triggers = {
             platform = "state";
             trigger = "state";
             entity_id = "binary_sensor.someid";
             entity_id = "binary_sensor.someid";
             to = "on";
             to = "on";
           };
           };
           condition = [
           conditions = [
             {
             {
               condition = "state";
               condition = "state";
Line 495: Line 457:
             }
             }
           ];
           ];
           action = [
           actions = [
             {
             {
               service = "notify.notify";
               action = "notify.notify";
               data = {
               data = {
                 message = "Some Notification";
                 message = "Some Notification";
Line 503: Line 465:
             }
             }
             {
             {
               service = "siren.turn_on";
               action = "siren.turn_on";
               entity_id = "siren.someid";
               entity_id = "siren.someid";
             }
             }
Line 515: Line 477:
         {
         {
           alias = "Some Name";
           alias = "Some Name";
           trigger = {
           triggers = {
             platform = "numeric_state";
             trigger = "numeric_state";
             entity_id = "sensor.batteries";
             entity_id = "sensor.batteries";
             below = "45";
             below = "45";
           };
           };
           action = {
           actions = {
             service = "notify.notify";
             action = "notify.notify";
             data = {
             data = {
               message = "Low Battery Detected";
               message = "Low Battery Detected";
Line 533: Line 495:
         {
         {
           alias = "Object Went Unknown";
           alias = "Object Went Unknown";
           trigger = {
           triggers = {
             platform = "state";
             trigger = "state";
             entity_id = "switch.someid";
             entity_id = "switch.someid";
             to = "unknown";
             to = "unknown";
             for = "00:5:00";
             for = "00:5:00";
           };
           };
           action = {
           actions = {
             service = "notify.notify";
             action = "notify.notify";
             data = {
             data = {
               message = "Object Went Offline";
               message = "Object Went Offline";
Line 553: Line 515:
         {
         {
           alias = "Do Something At Certain Time";
           alias = "Do Something At Certain Time";
           trigger = {
           triggers = {
             platform = "time";
             trigger = "time";
             at = "23:00:00";
             at = "23:00:00";
           };
           };
           action = {
           actions = {
             service = "climate.set_temperature";
             action = "climate.set_temperature";
             entity_id = "climate.thermostat";
             entity_id = "climate.thermostat";
             data = {
             data = {
Line 568: Line 530:
</syntaxhighlight>If you did not create any automations through the UI, Home Assistant will fail loading because the <code>automations.yaml</code> file does not exist yet, and it will fail including it. To avoid that, add a systemd tmpfiles.d rule:
</syntaxhighlight>If you did not create any automations through the UI, Home Assistant will fail loading because the <code>automations.yaml</code> file does not exist yet, and it will fail including it. To avoid that, add a systemd tmpfiles.d rule:


<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
systemd.tmpfiles.rules = [
systemd.tmpfiles.rules = [
   "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass"
   "f ${config.services.home-assistant.configDir}/automations.yaml 0644 hass hass"
];
];
</syntaxHighlight>
</syntaxhighlight>


== Trust a private certificate authority ==
== Trust a private certificate authority ==
Line 596: Line 558:
= Example configurations =
= Example configurations =


* [https://github.com/Mic92/dotfiles/tree/master/nixos/eve/modules/home-assistant Mic92's config]
* [https://github.com/Mic92/dotfiles/tree/393539385b0abfc3618e886cd0bf545ac24aeb67/machines/eve/modules/home-assistant Mic92's config]


= Misc =
= Misc =
Line 603: Line 565:


When developing Home Assistant for some test dependencies additional libraries are needed.
When developing Home Assistant for some test dependencies additional libraries are needed.
A nix-shell expression for this is available [https://github.com/nix-community/nix-environments here].
A nix-shell expression for this is available [https://github.com/nix-community/nix-environments/tree/master/envs/home-assistant here].
 
= Further reading =
 
* [https://nixcademy.com/posts/auto-update-containers/ Run and Auto-Update Docker (Home Assistant) Containers on NixOS], Nixcademy


[[Category:Applications]]
[[Category:Applications]]