Skip to content

Home Assistant

Home Assistant is installed natively as a NixOS service (services.home-assistant). It runs directly on the host OS for maximum performance and resource efficiency. It acts as the central hub for all smart home devices, including Zigbee, MQTT, and ESP32 integrations.

In this homelab, Home Assistant is enhanced with HACS (Home Assistant Community Store) for custom integrations and LLMs (OpenAI, Gemini, Anthropic, Ollama) for advanced voice conversation capabilities. Entities are exposed to voice platforms through the dedicated Matter Hub bridge rather than an in-instance integration.

PortProtocolPurpose
8123TCPWeb UI and API (Local)
Access MethodURL
Local networkhttp://<homelab.ip>:8123
Cloudflare Tunnelhttps://home-assistant-home.javiersc.com

The Home Assistant iOS/Android app does not natively support the Cloudflare Access login screen. For seamless mobile app access, use Tailscale: connect your phone to the Tailscale network and configure the Home Assistant app to use the Tailscale IP as both internal and external URL (e.g., http://100.82.100.68:8123).

Home Assistant uses 1Password for sensitive API keys (OpenAI, Anthropic, etc.). These are injected at the service level using the homelab secret management helpers.

Secret1Password ItemField
OpenAI API Keyop://Homelab/OpenAI/credentialAPI key for GPT-4 conversation
Anthropic API Keyop://Homelab/Anthropic/credentialAPI key for Claude conversation

Data is backed up daily to Backblaze B2 via Restic. To optimize storage and deduplication, we back up the raw files (database and configs) and explicitly exclude the compressed internal snapshots.

  • Restic Path: /var/lib/hass (excluding /backups)
  • Internal Snapshots: Managed via Home Assistant UI (Daily, Retention: 1-7 days). These are kept locally for fast “undo” operations but are not stored in the cloud.

Retention policy: 7 daily, 4 weekly, 6 monthly snapshots.

This homelab uses a hybrid approach to manage Home Assistant:

  • NixOS (modules/nixos/services/home-assistant.nix): Manages the base configuration, extra components, HACS, and static settings (external URLs, time zone, internal networking).
  • Home Assistant UI: Manages dynamic resources like Automations, Scripts, and Scenes.

To allow the UI to write these files without encountering permission errors (due to the read-only Nix Store), the Nix configuration explicitly points these resources to the mutable state directory (/var/lib/hass):

automation: !include /var/lib/hass/automations.yaml
script: !include /var/lib/hass/scripts.yaml
scene: !include /var/lib/hass/scenes.yaml

The system automatically creates these files with the correct permissions via systemd.tmpfiles.rules if they don’t exist.

If you create a script or automation in the UI, it will be saved to these files and will persist across NixOS rebuilds.

HACS is installed declaratively via NixOS by building the component from source in modules/nixos/services/home-assistant.nix. This approach avoids common Nixpkgs validation bugs (like the manifest.json KeyError) by using a manual derivation based on buildHomeAssistantComponent.

Multiple LLM components are enabled in the Nix configuration (extraComponents), including:

  • OpenAI Conversation
  • Google Generative AI (Gemini)
  • Anthropic
  • Ollama (Local LLM)
  • OpenRouter

The following Python packages are added via extraPackages:

  • aiogithubapi — Async GitHub API client used by integrations that interact with GitHub (e.g., HACS update checks).

The Home Assistant UI is configured for Spanish (es) localization. This affects date/time formats, number formatting, and the default language for the frontend.

To use MQTT in Home Assistant on NixOS, the mqtt component must be explicitly added to extraComponents in the Nix configuration. Without this, the required Python libraries (like paho-mqtt) will not be available, causing an “Unknown error” when trying to add the integration via the UI.

When configuring the MQTT integration in the UI:

  • Broker: Use localhost or 127.0.0.1. (If localhost fails to connect, try 127.0.0.1 to force IPv4).
  • Username/Password: Use the credentials managed in 1Password (Homelab/Mosquito).
  • Nanoleaf: Enabled via extraComponents. Discovery should find Nanoleaf devices automatically on the local network.
  • ESPHome: Native support for managing and controlling ESPHome-flashed devices.
    • Ball_v2 (ESP32-S3 + GC9A01A round display): Custom voice assistant device with I2S microphone/speaker, RGB LED (WS2812) for state feedback, and touch button. Microphone gain set to 12dB. LED colors indicate assistant state: green during listening, blue during thinking, and amber during replying. Config lives in assets/esphome/Ball_v2.yaml.

HA entities — including Zigbee devices bridged through Zigbee2MQTT — are exposed to Alexa, Apple Home, and Google Home by the Matter Hub. The Matter Hub runs as its own service and supersedes the legacy emulated_hue integration, which has been removed from modules/nixos/services/home-assistant.nix.

The esphome-config companion service renders secrets.yaml from 1Password via envsubst. A rm -f is issued before the redirect so that a stale 400-mode secrets.yaml left over from a previous boot cannot block startup with a “file exists” / read-only error. This is handled in modules/nixos/services/esphome.nix.

Symptom: HACS is installed via Nix but doesn’t show up in “Add Integration”.

Cause: Home Assistant UI cache might be stale.

Solution: Perform a “Hard Refresh” (Ctrl+F5) in your browser and ensure the home-assistant service has restarted.

Terminal window
systemctl restart home-assistant

Symptom: Nix build fails with “Python version mismatch”.

Cause: HACS or its dependencies are being built with a different Python version than the one used by Home Assistant.

Solution: Ensure all custom components and their dependencies use the same package set as Home Assistant: pkgs-unstable.home-assistant.python.pkgs.

”Leaked file descriptors” test blocks HA build (Python 3.14)

Section titled “”Leaked file descriptors” test blocks HA build (Python 3.14)”

Symptom: The Home Assistant Nix build fails during the serialx test phase with a “Leaked file descriptors” error under Python 3.14.

Cause: A flaky pytest in the serialx library reports leaked descriptors under the 3.14 test harness. The library itself works correctly at runtime; only the test suite fails.

Solution: A serialx override is applied in modules/nixos/services/home-assistant.nix to disable the flaky test. No functional change is required — this is a test-harness-only fix to unblock HA builds on Python 3.14.