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.
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).
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;
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.
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?
}