Home-Assistant Service

Table of Contents

Features
Usage
Debug
Options Reference

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://fogejo.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 LDAP block provided by Self Host Blocks to setup a LLDAP service. First, setup the global ldap block if not done yet:

shb.ldap = {
  enable = true;
  domain = "example.com";
  subdomain = "ldap";
  ssl = config.shb.certs.certs.letsencrypt."example.com";
  ldapPort = 3890;
  webUIListenPort = 17170;
  dcdomain = "dc=example,dc=com";
  ldapUserPassword.result = config.shb.sops.secrets."ldap/userPassword".result;
  jwtSecret.result = config.shb.sops.secrets."ldap/jwtSecret".result;
};

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

shb.sops.secrets."ldap/userPassword".request = config.shb.ldap.userPassword.request;
shb.sops.secrets."ldap/jwtSecret".request = config.shb.ldap.jwtSecret.request;

We then need to configure the home-assistant service to talk to the LDAP server we just defined:

shb.home-assistant.ldap
  enable = true;
  host = "127.0.0.1";
  port = config.shb.ldap.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.

Work is in progress to make the creation of the LDAP user and group declarative too.

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.

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

shb.home-assistant.enable

Whether to enable selfhostblocks.home-assistant.

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup

Backup configuration.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.request

Request part of the backup contract.

Options set by the requester module enforcing how to backup files.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.request.excludePatterns

File patterns to exclude.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.request.hooks

Hooks to run around the backup.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.request.hooks.afterBackup

Hooks to run after backup.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.request.hooks.beforeBackup

Hooks to run before backup.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.request.sourceDirectories

Directories to backup.

Type: non-empty (list of string)

Default:

[
  "/var/lib/hass/backups"
]

Example: "/var/lib/vaultwarden"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.request.user

Unix user doing the backups.

Type: string

Default: "hass"

Example: "vaultwarden"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.result

Result part of the backup contract.

Options set by the provider module that indicates the name of the backup and restor scripts.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.result.backupService

Name of service backing up the database.

This script can be ran manually to backup the database:

$ systemctl start backup.service

Type: string

Default: "backup.service"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.backup.result.restoreScript

Name of script that can restore the database. One can then list snapshots with:

$ restore snapshots

And restore the database with:

$ restore restore latest

Type: string

Default: "restore"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.config

See all available settings at https://www.home-assistant.io/docs/configuration/basic/

Type: attribute set of string

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.config.country

Two letter country code where this instance is located.

Type: string or (submodule)

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.config.latitude

Latitude where this instance is located.

Type: string or (submodule)

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.config.longitude

Longitude where this instance is located.

Type: string or (submodule)

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.config.name

Name of the Home Assistant instance.

Type: string or (submodule)

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.config.time_zone

Timezone of this instance.

Type: string or (submodule)

Example: "America/Los_Angeles"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.config.unit_system

Timezone of this instance.

Type: string or one of “metric”, “us_customary”

Example: "America/Los_Angeles"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.domain

domain under which home-assistant will be served.

Type: string

Example: "mydomain.com"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ldap

LDAP Integration App. Manual

Enabling this app will create a new LDAP configuration or update one that exists with the given host.

Also, enabling LDAP will skip onboarding otherwise Home Assistant gets into a cyclic lock.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ldap.enable

Whether to enable LDAP app…

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ldap.host

Host serving the LDAP server.

If set, the Home Assistant auth will be disabled. To keep it, set keepDefaultAuth to true.

Type: string

Default: "127.0.0.1"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ldap.keepDefaultAuth

Keep Home Assistant auth active, even if LDAP is configured. Usually, you want to enable this to transfer existing users to LDAP and then you can disabled it.

Type: boolean

Default: false

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ldap.port

Port of the service serving the LDAP server.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default: 389

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ldap.userGroup

Group users must belong to to be able to login to Nextcloud.

Type: string

Default: "homeassistant_user"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ssl

Path to SSL files

Type: null or (anything)

Default: null

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ssl.paths

Paths where the files for the certificate will be located.

This option is the contract output of the shb.certs.certs SSL block.

Type: anything

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ssl.paths.cert

Path to the cert file.

Type: absolute path

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ssl.paths.key

Path to the key file.

Type: absolute path

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.ssl.systemdService

Systemd oneshot service used to generate the certificate. Ends with the .service suffix.

Use this if downstream services must wait for the certificates to be generated before starting.

Type: string

Example: "cert-generator.service"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.subdomain

Subdomain under which home-assistant will be served.

Type: string

Example: "ha"

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.voice

Options related to voice service.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.voice.speech-to-text

Wyoming piper servers.

https://search.nixos.org/options?channel=23.11&from=0&size=50&sort=relevance&type=packages&query=services.wyoming.piper.servers

Type: attribute set of anything

Default: { }

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.voice.text-to-speech

Wyoming faster-whisper servers.

https://search.nixos.org/options?channel=23.11&from=0&size=50&sort=relevance&type=packages&query=services.wyoming.faster-whisper.servers

Type: attribute set of anything

Default: { }

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>
shb.home-assistant.voice.wakeword

Wyoming open wakework servers.

https://search.nixos.org/options?channel=23.11&from=0&size=50&sort=relevance&type=packages&query=services.wyoming.openwakeword

Type: anything

Default:

{
  enable = false;
}

Declared by:

<selfhostblocks/modules/services/home-assistant.nix>