Published : 2023-07-21

Home assistant on NixOS with docker and Bluetooth

Home assistant is a great home automation software and provided a distribution in order to run on various devices.

I won’t present it, as there is various topics on the net around it, but i’ll present how to run it on NixOS in a reproducible way.

NixOS uses nix to have reproducible buildable environments. It’s very powerful, and, regarding my experience with 10 years on Ansible and 7 years of Terraform, i think it’s the future of automation in reproducible environments.

Initial NixOS configuration

We can configure all with a single file, but let’s split it in multiple steps to understand what we are doing.

Here is the initial configuration (for raspberry PI), /etc/nixos/configuration.nix:

{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];

  nix.settings.auto-optimise-store = true;

  # Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
  boot.loader.grub.enable = false;
  # Enables the generation of /boot/extlinux/extlinux.conf
  boot.loader.generic-extlinux-compatible.enable = true;

  networking.hostName = "nixoslab-rpi3"; # Define your hostname.
  # Pick only one of the below networking options.
  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.
  # networking.networkmanager.enable = true;  # Easiest to use and most distros use this by default.

  # Set your time zone.
  time.timeZone = "Europe/Paris";
  users.users.nixos= {
    isNormalUser  = true;
    home  = "/home/nixos";
    description  = "NixOS";
    extraGroups  = [ "wheel" ];
    openssh.authorizedKeys.keys  = [];
  };

  security.sudo.wheelNeedsPassword = false;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
     vim
     curl
     libraspberrypi
   ];

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  services.openssh.enable = true;

  documentation.nixos.enable = false;
  nix.gc.automatic = true;
  nix.gc.options = "--delete-older-than 30d";
  boot.cleanTmpDir = true;

  # Copy the NixOS configuration file and link it from the resulting system
  # (/run/current-system/configuration.nix). This is useful in case you
  # accidentally delete configuration.nix.
  system.copySystemConfiguration = true;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "23.05"; # Did you read the comment?

}

With this basic configuration, we setup a NixOS 23.05 version, enable OpenSSH and create a user named nixos with no password and a ssh key (define it in the list).

Bluetooth configuration

Now we will enable bluetooth services. As it’s Nix, it’s just a single line declaration !

Add this in the configuration.nix file:

hardware.bluetooth.enable = true;

Docker configuration

For docker configuration, we will Docker and NixOS integration with it.

Add this in the configuration.nix file:

virtualisation = {
  backend = "docker";
  containers.homeassistant = {
    volumes = [
      "home-assistant:/config"
      "/var/run/dbus:/run/dbus:ro"
    ];
    environment.TZ = "Europe/Paris";
    image = "ghcr.io/home-assistant/home-assistant:2023.7.3";
    extraOptions = [
      "--network=host"
    ];
  };
};

This configuration bootstrap a home-assistant container with 2023.7.3 version, a volume named home-assistant which will persist accross container recreation and will be on disk, and mount the dbus socket in order to have bluetooth support in the container.

Final configuration$

Here is the full final configuration, just apply it on any NixOS setup and tada, you will have full OS with Home Assistant and Bluetooth support.

{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];

  hardware.bluetooth.enable = true;
  nix.settings.auto-optimise-store = true;

  # Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
  boot.loader.grub.enable = false;
  # Enables the generation of /boot/extlinux/extlinux.conf
  boot.loader.generic-extlinux-compatible.enable = true;

  networking.hostName = "nixoslab-rpi3"; # Define your hostname.
  # Pick only one of the below networking options.
  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.
  # networking.networkmanager.enable = true;  # Easiest to use and most distros use this by default.

  # Set your time zone.
  time.timeZone = "Europe/Paris";
  users.users.nixos= {
    isNormalUser  = true;
    home  = "/home/nixos";
    description  = "NixOS";
    extraGroups  = [ "wheel" ];
    openssh.authorizedKeys.keys  = [];
  };

  security.sudo.wheelNeedsPassword = false;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
     vim
     curl
     libraspberrypi
   ];

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  services.openssh.enable = true;

  virtualisation.oci-containers = {
    backend = "docker";
    containers.homeassistant = {
      volumes = [
        "home-assistant:/config"
        "/var/run/dbus:/run/dbus:ro"
      ];
      environment.TZ = "Europe/Paris";
      image = "ghcr.io/home-assistant/home-assistant:2023.7.3";
      extraOptions = [
        "--network=host"
      ];
    };
  };

  networking.firewall.enable = false;

  documentation.nixos.enable = false;
  nix.gc.automatic = true;
  nix.gc.options = "--delete-older-than 30d";
  boot.cleanTmpDir = true;

  # Copy the NixOS configuration file and link it from the resulting system
  # (/run/current-system/configuration.nix). This is useful in case you
  # accidentally delete configuration.nix.
  system.copySystemConfiguration = true;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "23.05"; # Did you read the comment?

}