fixed home assistant

This commit is contained in:
Leyla Becker 2025-07-12 15:00:59 -05:00
parent 1d7e0d11f0
commit 3ce9b625d1
6 changed files with 122 additions and 268 deletions

View file

@ -282,10 +282,11 @@
subdomain = "search"; subdomain = "search";
}; };
virt-home-assistant = { home-assistant = {
enable = false; enable = true;
networkBridge = "bond0"; subdomain = "home";
hostDevice = "0x10c4:0xea60"; openFirewall = true;
database = "postgres";
}; };
qbittorrent = { qbittorrent = {

View file

@ -6,7 +6,7 @@
dnsPort = 53; dnsPort = 53;
in { in {
options.host.adguardhome = { options.host.adguardhome = {
enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; enable = lib.mkEnableOption "should ad guard home be enabled on this computer";
directory = lib.mkOption { directory = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "/var/lib/AdGuardHome/"; default = "/var/lib/AdGuardHome/";

View file

@ -8,7 +8,7 @@
./jellyfin.nix ./jellyfin.nix
./forgejo.nix ./forgejo.nix
./searx.nix ./searx.nix
./virt-home-assistant.nix ./home-assistant.nix
./adguardhome.nix ./adguardhome.nix
./immich.nix ./immich.nix
./qbittorent.nix ./qbittorent.nix

View file

@ -1,130 +1,138 @@
{ {
lib, lib,
config, config,
inputs,
... ...
}: let }: let
configDir = "/var/lib/hass"; configDir = "/var/lib/hass";
dbUser = "hass";
in { in {
options.host.home-assistant = { options.services.home-assistant = {
enable = lib.mkEnableOption "should home-assistant be enabled on this computer";
subdomain = lib.mkOption { subdomain = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = "subdomain of base domain that home-assistant will be hosted at"; description = "subdomain of base domain that home-assistant will be hosted at";
default = "home-assistant"; default = "home-assistant";
}; };
database = lib.mkOption {
type = lib.types.enum [
"builtin"
"postgres"
];
description = "what database do we want to use";
default = "builtin";
};
}; };
config = lib.mkIf config.host.home-assistant.enable (lib.mkMerge [ config = lib.mkIf config.services.home-assistant.enable (lib.mkMerge [
{ {
virtualisation.libvirt = { host = {
swtpm.enable = true; reverse_proxy.subdomains.${config.services.home-assistant.subdomain} = {
connections."qemu:///session" = { target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}";
networks = [
{ websockets.enable = true;
definition = inputs.nix-virt.lib.network.writeXML (inputs.nix-virt.lib.network.templates.bridge forwardHeaders.enable = true;
{
uuid = "d57e37e2-311f-4e5c-a484-97c2210c2770"; extraConfig = ''
subnet_byte = 71; add_header Upgrade $http_upgrade;
}); add_header Connection \"upgrade\";
active = true;
} proxy_buffering off;
];
domains = [ proxy_read_timeout 90;
{ '';
definition = inputs.nix-virt.lib.domain.writeXML (inputs.nix-virt.lib.domain.templates.linux
{
name = "Home Assistant";
uuid = "c5cc0efc-6101-4c1d-be31-acbba203ccde";
memory = {
count = 4;
unit = "GiB";
};
# storage_vol = {
# pool = "MyPool";
# volume = "Penguin.qcow2";
# };
});
}
];
}; };
}; };
# systemd.tmpfiles.rules = [ services.home-assistant = {
# "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" configDir = configDir;
# ]; extraComponents = [
# services.home-assistant = { "met"
# enable = true; "radio_browser"
# configDir = configDir; "isal"
# extraComponents = [ "zha"
# "met" "jellyfin"
# "radio_browser" "webostv"
# "isal" "tailscale"
# "zha" "syncthing"
# "jellyfin" "sonos"
# "webostv" "analytics_insights"
# "tailscale" "unifi"
# "syncthing" "openweathermap"
# "sonos" "ollama"
# "analytics_insights" ];
# "unifi" config = {
# "openweathermap" http = {
# ]; server_port = 8123;
# config = { use_x_forwarded_for = true;
# http = { trusted_proxies = ["127.0.0.1" "::1"];
# server_port = 8082; ip_ban_enabled = true;
# use_x_forwarded_for = true; login_attempts_threshold = 10;
# trusted_proxies = ["127.0.0.1" "::1"]; };
# ip_ban_enabled = true; recorder.db_url = "postgresql://@/${dbUser}";
# login_attempts_threshold = 10; "automation manual" = [];
# }; "automation ui" = "!include automations.yaml";
# # recorder.db_url = "postgresql://@/${db_user}"; };
# "automation manual" = []; extraPackages = python3Packages:
# "automation ui" = "!include automations.yaml"; with python3Packages; [
# }; hassil
# extraPackages = python3Packages: numpy
# with python3Packages; [ gtts
# hassil ];
# numpy };
# gtts
# ];
# };
# host = {
# reverse_proxy.subdomains.${config.host.home-assistant.subdomain} = {
# target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}";
# websockets.enable = true; systemd.tmpfiles.rules = [
# forwardHeaders.enable = true; "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass"
];
# extraConfig = ''
# add_header Upgrade $http_upgrade;
# add_header Connection \"upgrade\";
# proxy_buffering off;
# proxy_read_timeout 90;
# '';
# };
# };
} }
(lib.mkIf (config.services.home-assistant.database == "postgres") {
host = {
postgres = {
enable = true;
extraUsers = {
${dbUser} = {
isClient = true;
createUser = true;
};
};
extraDatabases = {
${dbUser} = {
name = dbUser;
};
};
};
};
services.home-assistant = {
extraPackages = python3Packages:
with python3Packages; [
psycopg2
];
};
systemd.services.home-assistant = {
requires = [
config.systemd.services.postgresql.name
];
};
})
(lib.mkIf config.host.impermanence.enable { (lib.mkIf config.host.impermanence.enable {
# assertions = [ assertions = [
# { {
# assertion = config.services.home-assistant.configDir == configDir; assertion = config.services.home-assistant.configDir == configDir;
# message = "home assistant config directory does not match persistence"; message = "home assistant config directory does not match persistence";
# } }
# ]; ];
# environment.persistence."/persist/system/root" = { environment.persistence."/persist/system/root" = {
# enable = true; enable = true;
# hideMounts = true; hideMounts = true;
# directories = [ directories = [
# { {
# directory = configDir; directory = configDir;
# user = "hass"; user = "hass";
# group = "hass"; group = "hass";
# } }
# ]; ];
# }; };
}) })
]); ]);
} }

View file

@ -4,7 +4,7 @@
... ...
}: { }: {
options.host.podman = { options.host.podman = {
enable = lib.mkEnableOption "should home-assistant be enabled on this computer"; enable = lib.mkEnableOption "should podman be enabled on this computer";
macvlan = { macvlan = {
subnet = lib.mkOption { subnet = lib.mkOption {
type = lib.types.str; type = lib.types.str;

View file

@ -1,155 +0,0 @@
{
config,
lib,
pkgs,
...
}: {
options.services.virt-home-assistant = {
enable = lib.mkEnableOption "Wether to enable home assistant virtual machine";
networkBridge = lib.mkOption {
type = lib.types.str;
description = "what network bridge should we attach to the image";
};
hostDevice = lib.mkOption {
type = lib.types.str;
description = "what host devices should be attached to the image";
};
initialVersion = lib.mkOption {
type = lib.types.str;
description = "what home assistant image version should we pull for initial instal";
default = "15.0";
};
imageName = lib.mkOption {
type = lib.types.str;
description = "where should the image be installed to";
default = "home-assistant.qcow2";
};
installLocation = lib.mkOption {
type = lib.types.str;
description = "where should the image be installed to";
default = "/etc/hass";
};
virtualMachineName = lib.mkOption {
type = lib.types.str;
description = "what name should we give the virtual machine";
default = "home-assistant";
};
subdomain = lib.mkOption {
type = lib.types.str;
description = "subdomain of base domain that home-assistant will be hosted at";
default = "home-assistant";
};
};
config = lib.mkIf config.services.virt-home-assistant.enable (lib.mkMerge [
{
# environment.systemPackages = with pkgs; [
# virt-manager
# ];
# TODO: move this to external module and just have an assertion here that its enabled
# enable virtualization on the system
virtualisation = {
libvirtd = {
enable = true;
qemu.ovmf.enable = true;
};
};
# TODO: deactivation script?
# create service to install and start the container
systemd.services.virt-install-home-assistant = let
# TODO: all of these need to be escaped to be used in commands reliably
bridgedNetwork = config.services.virt-home-assistant.networkBridge;
hostDevice = config.services.virt-home-assistant.hostDevice;
virtualMachineName = config.services.virt-home-assistant.virtualMachineName;
imageName = config.services.virt-home-assistant.imageName;
installLocation = config.services.virt-home-assistant.installLocation;
installImage = "${installLocation}/${imageName}";
initialVersion = config.services.virt-home-assistant.initialVersion;
home-assistant-qcow2 = pkgs.fetchurl {
name = "home-assistant.qcow2";
url = "https://github.com/home-assistant/operating-system/releases/download/${initialVersion}/haos_ova-${initialVersion}.qcow2.xz";
hash = "sha256-V1BEjvvLNbMMKJVyMCmipjQ/3owoJteeVxoF9LDHo1U=";
postFetch = ''
cp $out src.xz
rm -r $out
${pkgs.xz}/bin/unxz src.xz --stdout > $out/${imageName}
'';
};
# Write a script to install the Home Assistant OS qcow2 image
virtInstallScript = pkgs.writeShellScriptBin "virt-install-hass" ''
# Copy the initial image out of the package store to the install location if we don't have one yet
if [ ! -f ${installImage} ]; then
cp ${home-assistant-qcow2} ${installLocation}
fi
# Check if VM already exists, and other pre-conditions
if ! ${pkgs.libvirt}/bin/virsh list --all | grep -q ${virtualMachineName}; then
${pkgs.virt-manager}/bin/virt-install --name ${virtualMachineName} \
--description "Home Assistant OS" \
--os-variant=generic \
--boot uefi \
--ram=2048 \
--vcpus=2 \
--import \
--disk ${installImage},bus=sata \
--network bridge=${bridgedNetwork} \
--host-device ${hostDevice} \
--graphics none
${pkgs.libvirt}/bin/virsh autostart ${virtualMachineName}
fi
'';
in {
description = "Install and start Home Assistant";
wantedBy = ["multi-user.target"];
after = ["local-fs.target"];
requires = ["libvirtd.service"];
serviceConfig.Type = "oneshot";
serviceConfig = {
ExecStart = "${virtInstallScript}/bin/virt-install-hass";
};
};
# TODO: figure out what we need to proxy to the virtual image
# host = {
# reverse_proxy.subdomains.${config.services.virt-home-assistant.subdomain} = {
# target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}";
# websockets.enable = true;
# forwardHeaders.enable = true;
# extraConfig = ''
# add_header Upgrade $http_upgrade;
# add_header Connection \"upgrade\";
# proxy_buffering off;
# proxy_read_timeout 90;
# '';
# };
# };
}
(lib.mkIf config.services.fail2ban.enable {
# TODO: figure out how to write a config for this, prob based on nginx proxy logs?
})
(lib.mkIf config.host.impermanence.enable {
# assertions = [
# {
# assertion = config.services.virt-home-assistant.installLocation == configDir;
# message = "home assistant install location does not match persistence";
# }
# ];
environment.persistence."/persist/system/root" = {
enable = true;
hideMounts = true;
directories = [
{
directory = config.services.virt-home-assistant.installLocation;
}
];
};
})
]);
}