selfhostblocks/modules/services/home-assistant/docs/default.md
2026-02-24 20:00:36 +01:00

14 KiB

Home-Assistant Service

Defined in /modules/services/home-assistant.nix.

This NixOS module is a service that sets up a Home-Assistant instance.

Compared to the stock module from nixpkgs, this one sets up, in a fully declarative manner LDAP and SSO integration.

Features

Usage

Initial Configuration

The following snippet enables Home-Assistant and makes it available under the ha.example.com endpoint.

shb.home-assistant = {
  enable = true;
  subdomain = "ha";
  domain = "example.com";

  config = {
    name = "SelfHostBlocks - Home Assistant";
    country.source = config.shb.sops.secret."home-assistant/country".result.path;
    latitude.source = config.shb.sops.secret."home-assistant/latitude_home".result.path;
    longitude.source = config.shb.sops.secret."home-assistant/longitude_home".result.path;
    time_zone.source = config.shb.sops.secret."home-assistant/time_zone".result.path;
    unit_system = "metric";
  };
};

shb.sops.secret."home-assistant/country".request = {
  mode = "0440";
  owner = "hass";
  group = "hass";
  restartUnits = [ "home-assistant.service" ];
};
shb.sops.secret."home-assistant/latitude_home".request = {
  mode = "0440";
  owner = "hass";
  group = "hass";
  restartUnits = [ "home-assistant.service" ];
};
shb.sops.secret."home-assistant/longitude_home".request = {
  mode = "0440";
  owner = "hass";
  group = "hass";
  restartUnits = [ "home-assistant.service" ];
};
shb.sops.secret."home-assistant/time_zone".request = {
  mode = "0440";
  owner = "hass";
  group = "hass";
  restartUnits = [ "home-assistant.service" ];
};

This assumes secrets are setup with SOPS as mentioned in the secrets setup section of the manual.

Any item in the config can be passed a secret, which means it will not appear in the /nix/store and instead be added to the config file out of band, here using sops. To do that, append .source to the settings name and give it the path to the secret.

I advise using secrets to set personally identifiable information, like shown in the snippet. Especially if you share your repository publicly.

Home-Assistant through HTTPS

:::: {.note} We will build upon the Initial Configuration section, so please follow that first. ::::

If the shb.ssl block is used (see manual on how to set it up), the instance will be reachable at https://ha.example.com.

Here is an example with Let's Encrypt certificates, validated using the HTTP method. First, set the global configuration for your domain:

shb.certs.certs.letsencrypt."example.com" = {
  domain = "example.com";
  group = "nginx";
  reloadServices = [ "nginx.service" ];
  adminEmail = "myemail@mydomain.com";
};

Then you can tell Home-Assistant to use those certificates.

shb.certs.certs.letsencrypt."example.com".extraDomains = [ "ha.example.com" ];

shb.home-assistant = {
  ssl = config.shb.certs.certs.letsencrypt."example.com";
};

With LDAP Support

:::: {.note} We will build upon the HTTPS section, so please follow that first. ::::

We will use the LLDAP block provided by Self Host Blocks. Assuming it has been set already, add the following configuration:

shb.home-assistant.ldap
  enable = true;
  host = "127.0.0.1";
  port = config.shb.lldap.webUIListenPort;
  userGroup = "homeassistant_user";
};

And that's it. Now, go to the LDAP server at http://ldap.example.com, create the home-assistant_user group, create a user and add it to one or both groups. When that's done, go back to the Home-Assistant server at http://home-assistant.example.com and login with that user.

With SSO Support

:::: {.warning} This is not implemented yet. Any contributions (issue #12) are welcomed! ::::

Backup

Backing up Home-Assistant using the Restic block is done like so:

shb.restic.instances."home-assistant" = {
  request = config.shb.home-assistant.backup;
  settings = {
    enable = true;
  };
};

The name "home-assistant" in the instances can be anything. The config.shb.home-assistant.backup option provides what directories to backup. You can define any number of Restic instances to backup Home-Assistant multiple times.

You will then need to configure more options like the repository, as explained in the restic documentation.

Application Dashboard

Integration with the dashboard contract is provided by the dashboard option.

For example using the Homepage service:

{
  shb.homepage.servicesGroups.Home.services.HomeAssistant = {
    sortOrder = 1;
    dashboard.request = config.shb.home-assistant.dashboard.request;
    settings.icon = "si-homeassistant";
  };
}

The icon needs to be set manually otherwise it is not displayed correctly.

An API key can be set to show extra info:

{
  shb.homepage.servicesGroups.Home.services.HomeAssistant = {
    apiKey.result = config.shb.sops.secret."home-assistant/homepageApiKey".result;
  };

  shb.sops.secret."home-assistant/homepageApiKey".request =
    config.shb.homepage.servicesGroups.Home.services.HomeAssistant.apiKey.request;
}

Custom widgets can be set using Home Assistant templating:

{
  shb.homepage.servicesGroups.Home.services.HomeAssistant = {
    settings.widget.custom = [
      {
        template = "{{ states('sensor.power_consumption_power_consumption', with_unit=True, rounded=True) }}";
        label = "energy now";
      }
      {
        state = "sensor.power_consumption_daily_power_consumption";
        label = "energy today";
      }
    ];
  };
}

Extra Components

Packaged components can be found in the documentation of the corresponding option services.home-assistant.extraComponents

When you find an interesting one add it to the option:

services.home-assistant.extraComponents = [
  "backup"
  "bluetooth"
  "esphome"

  "assist_pipeline"
  "conversation"
  "piper"
  "wake_word"
  "whisper"
  "wyoming"
];

Some components are not available as extra components, but need to be added as cusotm components. If the component is not packaged, you'll need to use a custom component.

Custom Components

:::: {.note} I'm still confused for why is there a difference between custom components and extra components. ::::

Available custom components can be found by searching packages for home-assistant-custom-components.

Add them like so:

services.home-assistant.customComponents = with pkgs.home-assistant-custom-components; [
  adaptive_lighting
];

To add a not packaged component, you can get inspiration from existing [packaged components. To help you package a custom component nixpkgs code to package it using the pkgs.buildHomeAssistantComponent function.

When done, add it to the same services.home-assistant.customComponents option. Also, don't hesitate to upstream it to nixpkgs.

Custom Lovelace Modules

To add custom Lovelace UI elements, add them to the services.home-assistant.customLovelaceModules option. Available custom components can be found by searching packages for home-assistant-custom-lovelace-modules.

services.home-assistant.customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
  mini-graph-card
  mini-media-player
  hourly-weather
  weather-card
];

Extra Packages

This is really only needed if by mischance, one of the components added earlier fail because of a missing Python3 package when the home-assistant systemd service is started. Usually, the required module will be shown in the traceback. To know to which nixpkgs package this Python3 package correspond, search for a package in the python3XXPackages set.

services.home-assistant.extraPackages = python3Packages: with python3Packages; [
  grpcio
];

Extra Groups

Some components need access to hardware components which mean the home-assistant user hass must be added to some Unix group. For example, the hass user must be added to the dialout group for the Sonoff component.

There's no systematic way to know this apart reading the logs when a home-assistant component fails to start.

users.users.hass.extraGroups = [ "dialout" ];

Voice

Text to speech (TTS) and speech to text (STT) can be added with the stock nixpkgs options. The most performance hungry one is STT. If you don't have a good CPU or better a GPU, you won't be able to use medium to big models. From my own experience using a low-end CPU, voice is pretty much unusable like that, even with mini models.

Here is the configuration I use on a low-end CPU:

shb.home-assistant.voice.text-to-speech = {
  "fr" = {
    enable = true;
    voice = "fr-siwis-medium";
    uri = "tcp://0.0.0.0:10200";
    speaker = 0;
  };
  "en" = {
    enable = true;
    voice = "en_GB-alba-medium";
    uri = "tcp://0.0.0.0:10201";
    speaker = 0;
  };
};
shb.home-assistant.voice.speech-to-text = {
  "tiny-fr" = {
    enable = true;
    model = "base-int8";
    language = "fr";
    uri = "tcp://0.0.0.0:10300";
    device = "cpu";
  };
  "tiny-en" = {
    enable = true;
    model = "base-int8";
    language = "en";
    uri = "tcp://0.0.0.0:10301";
    device = "cpu";
  };
};
systemd.services.wyoming-faster-whisper-tiny-en.environment."HF_HUB_CACHE" = "/tmp";
systemd.services.wyoming-faster-whisper-tiny-fr.environment."HF_HUB_CACHE" = "/tmp";
shb.home-assistant.voice.wakeword = {
  enable = true;
  uri = "tcp://127.0.0.1:10400";
  preloadModels = [
    "ok_nabu"
  ];
};

Music Assistant

To add Music Assistant under the ma.example.com domain with two factor SSO authentication, use the following configuration. This assumes the SSL and SSO blocks are configured.

services.music-assistant = {
  enable = true;
  providers = [
    "airplay"
    "hass"
    "hass_players"
    "jellyfin"
    "radiobrowser"
    "sonos"
    "spotify"
  ];
};

shb.nginx.vhosts = [
  {
    subdomain = "ma";
    domain = "example.com";
    ssl = config.shb.certs.certs.letsencrypt.${domain};
    authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
    upstream = "http://127.0.0.1:8095";
    autheliaRules = [{
      domain = "ma.${domain}";
      policy = "two_factor";
      subject = ["group:music-assistant_user"];
    }];
  }
];

Debug

In case of an issue, check the logs for systemd service home-assistant.service.

Enable verbose logging by setting the shb.home-assistant.debug boolean to true.

Access the database with sudo -u home-assistant psql.

Options Reference

id-prefix: services-home-assistant-options-
list-id: selfhostblocks-service-home-assistant-options
source: @OPTIONS_JSON@